diff --git a/.changeset/dirty-balloons-develop.md b/.changeset/dirty-balloons-develop.md new file mode 100644 index 0000000000..6dd9005cca --- /dev/null +++ b/.changeset/dirty-balloons-develop.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +Bump `swagger-ui-react` to `^4.0.0-rc.3`. diff --git a/.changeset/happy-hotels-explain.md b/.changeset/happy-hotels-explain.md new file mode 100644 index 0000000000..ede18c3187 --- /dev/null +++ b/.changeset/happy-hotels-explain.md @@ -0,0 +1,7 @@ +--- +'@backstage/core-app-api': patch +'@backstage/core-components': patch +'@backstage/theme': patch +--- + +Internal refactor to avoid importing all of `@material-ui/core`. diff --git a/.changeset/large-pots-invent.md b/.changeset/large-pots-invent.md new file mode 100644 index 0000000000..269b0bd288 --- /dev/null +++ b/.changeset/large-pots-invent.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Support `material-ui` overrides in SystemDiagramCard and EmptityLinksEmptyState components diff --git a/.changeset/lemon-actors-wait.md b/.changeset/lemon-actors-wait.md new file mode 100644 index 0000000000..e98adc891e --- /dev/null +++ b/.changeset/lemon-actors-wait.md @@ -0,0 +1,15 @@ +--- +'@backstage/plugin-home': patch +--- + +Adds a `` component that shows a playful greeting on the home page. +To use it, pass it to the home page header: + +```typescript + +
} pageTitleOverride="Home"> + +
+ … +
+``` diff --git a/.changeset/neat-cooks-sell.md b/.changeset/neat-cooks-sell.md new file mode 100644 index 0000000000..11859c3589 --- /dev/null +++ b/.changeset/neat-cooks-sell.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': patch +--- + +Fix search in Firefox. When the search was performed by pressing enter, the query parameter was first set but then reverted back. diff --git a/.changeset/silent-candles-remember.md b/.changeset/silent-candles-remember.md new file mode 100644 index 0000000000..51700c4582 --- /dev/null +++ b/.changeset/silent-candles-remember.md @@ -0,0 +1,5 @@ +--- +'@backstage/core-components': minor +--- + +The syntax highlighting library used by the `CodeSnippet` component is now lazy loaded. This most likely has no effect on existing code, but may break tests as the content of the `CodeSnippet` is now rendered asynchronously. diff --git a/.changeset/six-pumpkins-lie.md b/.changeset/six-pumpkins-lie.md new file mode 100644 index 0000000000..7f28582d91 --- /dev/null +++ b/.changeset/six-pumpkins-lie.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-backend': patch +--- + +This change refactors the internal package structure to remove the `next` catalog folder that was used during the implementation and testing phase of the new catalog engine. The implementation is now the default and is therefore restructured to no longer be packaged under `next/`. This refactor does not change catalog imports from other parts of the project. diff --git a/.changeset/smart-seahorses-ring.md b/.changeset/smart-seahorses-ring.md new file mode 100644 index 0000000000..a5ae156afd --- /dev/null +++ b/.changeset/smart-seahorses-ring.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Update default backend ESLint configuration to allow usage of `__dirname` in tests. diff --git a/.changeset/stale-seahorses-sell.md b/.changeset/stale-seahorses-sell.md new file mode 100644 index 0000000000..2fa52b109f --- /dev/null +++ b/.changeset/stale-seahorses-sell.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-azure-devops-backend': patch +--- + +Expands the Azure DevOps backend plugin to provide pull request data to be used by the front end plugin diff --git a/.changeset/two-foxes-marry.md b/.changeset/two-foxes-marry.md new file mode 100644 index 0000000000..a6ac7df666 --- /dev/null +++ b/.changeset/two-foxes-marry.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-home': patch +--- + +Fix `` to display only the selected tab, not the other way around. diff --git a/.changeset/wise-clocks-accept.md b/.changeset/wise-clocks-accept.md new file mode 100644 index 0000000000..7b9090937b --- /dev/null +++ b/.changeset/wise-clocks-accept.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog-react': patch +--- + +Support `material-ui` overrides in plugin-catalog-react components diff --git a/ADOPTERS.md b/ADOPTERS.md index 5fafdb5da4..21d1419a45 100644 --- a/ADOPTERS.md +++ b/ADOPTERS.md @@ -55,3 +55,4 @@ | [Santagostino](https://santagostino.it) | [@santagostino](https://github.com/santagostino) | Developer portal, gateway to our infrastructure, documentation, service catalog and internal tooling. | | [Peak](https://peak.ai) | [Luke Beamish](https://github.com/lukebeamish-peak) | Developer portal for all internal engineers to access documentation and tooling. | | [Gelato](https://gelato.com/) | [Dmitry Makarenko](https://github.com/dmitry-makarenko-gelato) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal and third-party systems🚀. | +| [GoCardless](https://gocardless.com/) | [James Turley](https://github.com/tragiclifestories) | Developer portal: documentation, service templates, org structure, service catalog, plugins for integration with internal systems. | \ No newline at end of file diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 5242309eee..99d63cf0b4 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -129,9 +129,10 @@ In general, changesets are not needed for the documentation, build utilities, co 1. Run `yarn changeset` 2. Select which packages you want to include a changeset for 3. Select impact of change that you're introducing, using `minor` for breaking changes and `patch` otherwise. We do not use `major` changes while packages are at version `0.x`. -4. Add generated changeset to Git -5. Push the commit with your changeset to the branch associated with your PR -6. Accept our gratitude for making the release process easier on the maintainers +4. Explain your changes in the generated changeset. See [examples of well written changesets](https://backstage.io/docs/getting-started/contributors#writing-changesets). +5. Add generated changeset to Git +6. Push the commit with your changeset to the branch associated with your PR +7. Accept our gratitude for making the release process easier on the maintainers For more information, checkout [adding a changeset](https://github.com/atlassian/changesets/blob/master/docs/adding-a-changeset.md) documentation in the changesets repository. diff --git a/docs/getting-started/contributors.md b/docs/getting-started/contributors.md index e12c0c5f17..ed56d63cab 100644 --- a/docs/getting-started/contributors.md +++ b/docs/getting-started/contributors.md @@ -139,3 +139,92 @@ default app configs. You can learn more about the local configuration in [Static Configuration in Backstage](../conf/) section. + +## Writing changesets + +Changesets are an important part of the development process. They are used to +generate Changelog entries for all changes to the project. Ultimately they are +read by the end users to learn about important changes and fixes to the project. +Some of these fixes might require manual intervention from users so it's +important to write changesets that users understand and can take action on. + +Here are some important do's and don'ts when writing changesets: + +### Changeset should give a clear description to what has changed + +#### Bad + +``` +--- +'@backstage/catalog': patch +--- +Fixed table layout +``` + +#### Good + +``` +--- +'@backstage/catalog': patch +--- + +Fixed bug in EntityTable component where table layout did not readjust properly below 1080x768 pixels. +``` + +### Breaking changes not caught by the type checker should be clearly marked with bold **BREAKING** text + +#### Bad + +``` +--- +'@backstage/catalog': minor +--- + +getEntity is now a function that returns a Promise. +``` + +#### Good + +``` +--- +'@backstage/catalog': minor +--- + +**BREAKING** The getEntity function now returns a Promise and **must** be awaited from now on. +``` + +### Changes to code should include a diff of the files that need updating + +#### Bad + +``` +--- +'@backstage/catalog': patch +--- + +**BREAKING** The catalogEngine now requires a flux capacitor to be passed. +``` + +#### Good + + --- + '@backstage/catalog': patch + --- + + **BREAKING** The catalog createRouter now requires that a `FluxCapacitor` is + passed to the router. + + These changes are **required** to `packages/backend/src/plugins/catalog.ts` + + ```diff + + import { FluxCapacitor } from '@backstage/time'; + + const fluxCapacitor = new FluxCapacitor(); + return await createRouter({ + entitiesCatalog, + locationAnalyzer, + locationService, + + fluxCapacitor, + logger: env.logger, + config: env.config, + }); + ``` diff --git a/docs/integrations/google-analytics/installation.md b/docs/integrations/google-analytics/installation.md deleted file mode 100644 index d6c23cc4b0..0000000000 --- a/docs/integrations/google-analytics/installation.md +++ /dev/null @@ -1,23 +0,0 @@ ---- -id: installation -title: Google Analytics Installation -sidebar_label: Installation -# prettier-ignore -description: Adding Google Analytics to Your App ---- - -There is a basic -[Google Analytics](https://marketingplatform.google.com/about/analytics/) -integration built into Backstage. You can enable it by adding the following to -your app configuration: - -```yaml -app: - googleAnalyticsTrackingId: UA-000000-0 -``` - -Replace the tracking ID with the one generated for you after signing up for the -Google Analytics service. - -The default behavior is only to send a pageview hit. To record more, review the -[Google Analytics developer documentation](https://developers.google.com/analytics/devguides/collection/gtagjs). diff --git a/docs/plugins/analytics.md b/docs/plugins/analytics.md new file mode 100644 index 0000000000..0b3d5dfd9c --- /dev/null +++ b/docs/plugins/analytics.md @@ -0,0 +1,298 @@ +--- +id: analytics +title: Plugin Analytics +description: Measuring usage of your Backstage instance. +--- + +Setting up, maintaining, and iterating on an instance of Backstage can be a +large investment. To help measure return on this investment, Backstage comes +with an event-based Analytics API that grants app integrators the flexibility to +collect and analyze Backstage usage in the analytics tool of their choice, while +providing plugin developers a standard interface for instrumenting key user +interactions. + +## Concepts + +- **Events** consist of, at a minimum, an `action` (like `click`) and a + `subject` (like `thing that was clicked on`). +- **Attributes** represent additional dimensional data (in the form of key/value + pairs) that may be provided on an event-by-event basis. To continue the above + example, the URL a user clicked to might look like `{ "to": "/a/page" }`. +- **Context** represents the broader context in which an event took place. By + default, information like `pluginId`, `extension`, and `routeRef` are + provided. + +This composition of events aims to allow analysis at different levels of detail, +enabling very granular questions (like "what is the most clicked on thing on a +particular route") as well as very high-level questions (like "what is the most +used plugin in my Backstage instance") to be answered. + +## Supported Analytics Tools + +While all that's needed to consume and forward these events to an analytics tool +is a concrete implementation of [AnalyticsApi][analytics-api-type], common +integrations are packaged and provided as plugins. Find your analytics tool of +choice below. + +| Analytics Tool | Support Status | +| ---------------------- | -------------- | +| [Google Analytics][ga] | Yes ✅ | + +To suggest an integration, please [open an issue][add-tool] for the analytics +tool your organization uses. Or jump to [Writing Integrations][int-howto] to +learn how to contribute the integration yourself! + +[ga]: + https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga/README.md +[add-tool]: + https://github.com/backstage/backstage/issues/new?assignees=&labels=plugin&template=plugin_template.md&title=%5BAnalytics+Module%5D+THE+ANALYTICS+TOOL+TO+INTEGRATE +[int-howto]: #writing-integrations +[analytics-api-type]: + https://backstage.io/docs/reference/core-plugin-api.analyticsapi + +## Key Events + +The following table summarizes events that, depending on the plugins you have +installed, may be captured. + +| Action | Provided By | Subject | +| ---------- | -------------- | ----------------------------------------- | +| `navigate` | Backstage Core | The URL of the page that was navigated to | +| `click` | Backstage Core | The text of the link that was clicked on | + +If there is an event you'd like to see captured, please [open an +issue][add-event] describing the event you want to see and the questions it +would help you answer. Or jump to [Capturing Events][event-howto] to learn how +to contribute the instrumentation yourself! + +_OSS plugin maintainers: feel free to document your events in the table above._ + +[add-event]: +https://github.com/backstage/backstage/issues/new?assignees=&labels=enhancement&template=feature_template.md&title=[Analytics%20Event]:%20THE+EVENT+TO+CAPTURE +[event-howto]: #capturing-events + +## Writing Integrations + +Analytics event forwarding is implemented as a Backstage utility API. Just as +you might provide a custom API implementation for errors or SCM Authentication, +you can provide one for analytics. + +The provided API need only provide a single method `captureEvent`, which takes +an `AnalyticsEvent` object. + +```ts +import { + analyticsApiRef, + AnalyticsEvent, + AnyApiFactory, + createApiFactory, +} from '@backstage/core-plugin-api'; + +export const apis: AnyApiFactory[] = [ + createApiFactory(analyticsApiRef, { + captureEvent: (event: AnalyticsEvent) => { + window._AcmeAnalyticsQ.push(event); + }, + }), +]; +``` + +In reality, you would likely want to encapsulate instantiation logic and pull +some details from configuration. A more complete example might look like: + +```ts +import { + AnalyticsApi, + analyticsApiRef, + AnalyticsEvent, + AnyApiFactory, + configApiRef, + createApiFactory, +} from '@backstage/core-plugin-api'; +import { AcmeAnalytics } from 'acme-analytics'; + +class AcmeAnalytics implements AnalyticsApi { + private constructor(accountId: number) { + AcmeAnalytics.init(accountId); + } + + static fromConfig(config) { + const accountId = config.getString('app.analytics.acme.id'); + return new AcmeAnalytics(accountId); + } + + captureEvent(event: AnalyticsEvent) { + const { action, ...rest } = event; + AcmeAnalytics.send(action, rest); + } +} + +export const apis: AnyApiFactory[] = [ + createApiFactory({ + api: analyticsApiRef, + deps: { configApi: configApiRef }, + factory: ({ configApi }) => AcmeAnalytics.fromConfig(configApi), + }), +]; +``` + +If you are integrating with an analytics service (as opposed to an internal +tool), consider contributing your API implementation as a plugin! + +By convention, such packages should be named +`@backstage/analytics-module-[name]`, and any configuration should be keyed +under `app.analytics.[name]`. + +## Capturing Events + +To instrument an event in a component, start by retrieving an analytics tracker +using the `useAnalytics()` hook provided by `@backstage/core-plugin-api`. The +tracker includes a `captureEvent` method which takes an `action` and a `subject` +as arguments. + +```ts +import { useAnalytics } from '@backstage/core-plugin-api'; + +const analytics = useAnalytics(); +analytics.captureEvent('deploy', serviceName); +``` + +### Providing Extra Attributes + +Additional dimensional `attributes` as well as a numeric `value` can be provided +on a third `options` argument if/when relevant for the event: + +```ts +analytics.captureEvent('merge', pullRequestName, { + value: pullRequestAgeInMinutes, + attributes: { + org, + repo, + }, +}); +``` + +In the above example, an event resembling the following object would be +captured: + +```json +{ + "action": "merge", + "subject": "Name of Pull Request", + "value": 60, + "attributes": { + "org": "some-org", + "repo": "some-repo" + } +} +``` + +### Providing Context for Events + +The `attributes` option is good for capturing details available to you within +the component that you're instrumenting. For capturing metadata only available +further up the react tree, or to help app integrators aggregate distinct events +by some common value, use an ``. + +```tsx +import { AnalyticsContext, useAnalytics } from '@backstage/core-plugin-api'; + +const MyComponent = ({ value }) => { + const analytics = useAnalytics(); + const handleClick = () => analytics.captureEvent('check', value); + return ; +}; + +const MyWrapper = () => { + return ( + + + + ); +}; +``` + +In the above example, clicking on `` would result in an analytics +event resembling: + +```json +{ + "action": "check", + "subject": "Some Value", + "context": { + "segment": "xyz" + } +} +``` + +Note that, for brevity in the example above, the context keys provided by +Backstage core (`pluginId`, `extension`, and `routeRef`) have been omitted. In +reality, those details would be included alongside any additional context +provided by you. + +Analytics contexts can be nested; their values are merged down the react tree, +allowing keys to be overwritten. + +### Event Naming Considerations + +An event is split into its constituent parts to enable analysis at various +levels of granularity. In order to maintain this flexibility at analysis-time, +it's important to keep each of these levels of detail disaggregated. + +- Avoid providing an overly specific `action`. For example, instead of + `filterEntityTable`, consider just using `filter` as the action, and allowing + `EntityTable` to be specified as part of the event's `context` (most likely + automatically as part of the `extension` in which the `filter` event was + captured). + +- On the flip side, when adding `attributes` to an event, look at existing + events and see if the data you are capturing matches the intention, type, or + even the content of _their_ `attributes`. For instance, it may be common for + events that involve the Catalog to add details like entity `name`, `kind`, + and/or `namespace` as `attributes`. Using the same keys in your event will + ensure that events instrumented across plugins can easily be aggregated. + +### Unit Testing Event Capture + +The `@backstage/test-utils` package includes a `MockAnalyticsApi` implementation +that you can use in your unit tests to spy on and make assertions about any +analytics events captured. + +Use it like this: + +```tsx +import { ApiProvider, ApiRegistry } from '@backstage/core-app-api'; +import { analyticsApiRef } from '@backstage/core-plugin-api'; +import { MockAnalyticsApi, wrapInTestApp } from '@backstage/test-utils'; +import { render, fireEvent, waitFor } from '@testing-library/react'; + +describe('SomeComponent', () => { + it('should capture event on click', () => { + // Use the Mock Analytics API to spy on event captures. + const apiSpy = new MockAnalyticsApi(); + + // Render the component being tested + const { getByText } = render( + wrapInTestApp( + + + , + ), + ); + + // Fire the event that triggers event capture. + fireEvent.click(getByText('some component text')); + + // Assert that the event was captured with the expected data. + await waitFor(() => { + expect(apiSpy.getEvents()[0]).toMatchObject({ + action: 'expected action', + subject: 'expected subject'', + attributes: { + foo: 'bar', + }, + }); + }); + }); +}); +``` diff --git a/docs/plugins/github-apps.md b/docs/plugins/github-apps.md index ef0b21d902..1be1502b6b 100644 --- a/docs/plugins/github-apps.md +++ b/docs/plugins/github-apps.md @@ -60,7 +60,7 @@ The YAML file must include the following information. Please note that the indentation for the `privateKey` is required. ```yaml -appId: 1 +appId: app id clientId: client id clientSecret: client secret webhookSecret: webhook secret @@ -95,7 +95,7 @@ If you want to limit the GitHub app installations visible to backstage you may optionally include the `allowedInstallationOwners` option. ```yaml -appId: 1 +appId: app id allowedInstallationOwners: ['GlobexCorp'] clientId: client id clientSecret: client secret diff --git a/docs/plugins/observability.md b/docs/plugins/observability.md index b5a6a0ba60..d8778f07f8 100644 --- a/docs/plugins/observability.md +++ b/docs/plugins/observability.md @@ -8,11 +8,6 @@ description: Adding Observability to Your Plugin This article briefly describes the observability options that are available to a Backstage integrator. -## Google Analytics - -See how to install Google Analytics in your app -[here](../integrations/google-analytics/installation.md) - ## Datadog RUM Events See how to install Datadog Events in your app diff --git a/microsite/data/plugins/backstage-analytics-module-ga.yaml b/microsite/data/plugins/backstage-analytics-module-ga.yaml new file mode 100644 index 0000000000..0a03ec20e8 --- /dev/null +++ b/microsite/data/plugins/backstage-analytics-module-ga.yaml @@ -0,0 +1,9 @@ +--- +title: 'Analytics Module: Google Analytics' +author: Spotify +authorUrl: https://github.com/spotify +category: Analytics +description: Track usage of your Backstage instance using Google Analytics. +documentation: https://github.com/backstage/backstage/blob/master/plugins/analytics-module-ga/README.md +iconUrl: img/ga-icon.png +npmPackageName: '@backstage/plugin-analytics-module-ga' diff --git a/microsite/data/plugins/grafana.yaml b/microsite/data/plugins/grafana.yaml new file mode 100644 index 0000000000..ff4e33e3df --- /dev/null +++ b/microsite/data/plugins/grafana.yaml @@ -0,0 +1,13 @@ +--- +title: Grafana +author: K-Phoen +authorUrl: https://github.com/K-Phoen +category: Monitoring +description: Associate alerts and dashboards to components. +documentation: https://github.com/K-Phoen/backstage-plugin-grafana/ +iconUrl: https://avatars.githubusercontent.com/u/7195757?s=200&v=4 +npmPackageName: '@k-phoen/backstage-plugin-grafana' +tags: + - dashboards + - monitoring + - alerting diff --git a/microsite/sidebars.json b/microsite/sidebars.json index bb9fd5783a..c269f8ac8f 100644 --- a/microsite/sidebars.json +++ b/microsite/sidebars.json @@ -154,11 +154,6 @@ "label": "GitLab", "ids": ["integrations/gitlab/locations"] }, - { - "type": "subcategory", - "label": "Google Analytics", - "ids": ["integrations/google-analytics/installation"] - }, { "type": "subcategory", "label": "Google GCS", @@ -178,6 +173,7 @@ "plugins/structure-of-a-plugin", "plugins/integrating-plugin-into-software-catalog", "plugins/composability", + "plugins/analytics", { "type": "subcategory", "label": "Backends and APIs", diff --git a/microsite/static/img/ga-icon.png b/microsite/static/img/ga-icon.png new file mode 100644 index 0000000000..8eaebd06aa Binary files /dev/null and b/microsite/static/img/ga-icon.png differ diff --git a/mkdocs.yml b/mkdocs.yml index 7376893586..2f4aa4203f 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -100,8 +100,6 @@ nav: - Org Data: 'integrations/github/org.md' - GitLab: - Locations: 'integrations/gitlab/locations.md' - - Google Analytics: - - Installation: 'integrations/google-analytics/installation.md' - Google GCS: - Locations: 'integrations/google-cloud-storage/locations.md' - LDAP: @@ -115,6 +113,7 @@ nav: - Plugin Development: 'plugins/plugin-development.md' - Integrate into the Software Catalog: 'plugins/integrating-plugin-into-software-catalog.md' - Composability System: 'plugins/composability.md' + - Plugin Analytics: 'plugins/analytics.md' - Backends and APIs: - Proxying: 'plugins/proxying.md' - Backend plugin: 'plugins/backend-plugin.md' diff --git a/package.json b/package.json index 03a502fee2..9c0f41ca53 100644 --- a/package.json +++ b/package.json @@ -61,7 +61,6 @@ "devDependencies": { "@types/webpack": "^5.28.0", "@changesets/cli": "^2.14.0", - "@octokit/openapi-types": "^2.2.0", "@spotify/prettier-config": "^11.0.0", "command-exists": "^1.2.9", "concurrently": "^6.0.0", @@ -71,7 +70,6 @@ "lerna": "^4.0.0", "lint-staged": "^11.1.2", "prettier": "^2.2.1", - "recursive-readdir": "^2.2.2", "shx": "^0.3.2", "yarn-lock-check": "^1.0.5" }, diff --git a/packages/app/src/components/home/HomePage.tsx b/packages/app/src/components/home/HomePage.tsx index ebb486790d..33ac1a7e8c 100644 --- a/packages/app/src/components/home/HomePage.tsx +++ b/packages/app/src/components/home/HomePage.tsx @@ -14,25 +14,26 @@ * limitations under the License. */ -import React from 'react'; -import Grid from '@material-ui/core/Grid'; -import { - HomePageRandomJoke, - ComponentAccordion, - ComponentTabs, - ComponentTab, -} from '@backstage/plugin-home'; import { Content, Header, - Page, HomepageTimer, + Page, } from '@backstage/core-components'; +import { + ComponentAccordion, + ComponentTab, + ComponentTabs, + HomePageRandomJoke, + WelcomeTitle, +} from '@backstage/plugin-home'; import { HomePageSearchBar } from '@backstage/plugin-search'; +import Grid from '@material-ui/core/Grid'; +import React from 'react'; export const HomePage = () => ( -
+
} pageTitleOverride="Home">
diff --git a/packages/backend-common/src/reading/AwsS3UrlReader.test.ts b/packages/backend-common/src/reading/AwsS3UrlReader.test.ts index 80f59fe182..0bc0e4f97f 100644 --- a/packages/backend-common/src/reading/AwsS3UrlReader.test.ts +++ b/packages/backend-common/src/reading/AwsS3UrlReader.test.ts @@ -135,13 +135,7 @@ describe('AwsS3UrlReader', () => { 'getObject', Buffer.from( require('fs').readFileSync( - path.resolve( - 'src', - 'reading', - '__fixtures__', - 'awsS3', - 'awsS3-mock-object.yaml', - ), + path.resolve(__dirname, '__fixtures__/awsS3/awsS3-mock-object.yaml'), ), ), ); @@ -187,13 +181,7 @@ describe('AwsS3UrlReader', () => { 'getObject', Buffer.from( require('fs').readFileSync( - path.resolve( - 'src', - 'reading', - '__fixtures__', - 'awsS3', - 'awsS3-mock-object.yaml', - ), + path.resolve(__dirname, '__fixtures__/awsS3/awsS3-mock-object.yaml'), ), ), ); @@ -249,13 +237,7 @@ describe('AwsS3UrlReader', () => { 'getObject', Buffer.from( require('fs').readFileSync( - path.resolve( - 'src', - 'reading', - '__fixtures__', - 'awsS3', - 'awsS3-mock-object.yaml', - ), + path.resolve(__dirname, '__fixtures__/awsS3/awsS3-mock-object.yaml'), ), ), ); diff --git a/packages/backend-common/src/reading/AzureUrlReader.test.ts b/packages/backend-common/src/reading/AzureUrlReader.test.ts index e014fa2e75..59968a18e9 100644 --- a/packages/backend-common/src/reading/AzureUrlReader.test.ts +++ b/packages/backend-common/src/reading/AzureUrlReader.test.ts @@ -152,7 +152,7 @@ describe('AzureUrlReader', () => { describe('readTree', () => { const repoBuffer = fs.readFileSync( - path.resolve('src', 'reading', '__fixtures__', 'mock-main.zip'), + path.resolve(__dirname, '__fixtures__/mock-main.zip'), ); const processor = new AzureUrlReader( @@ -264,7 +264,7 @@ describe('AzureUrlReader', () => { describe('search', () => { const repoBuffer = fs.readFileSync( - path.resolve('src', 'reading', '__fixtures__', 'mock-main.zip'), + path.resolve(__dirname, '__fixtures__/mock-main.zip'), ); const processor = new AzureUrlReader( diff --git a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts index ef61452163..5bbf3725ea 100644 --- a/packages/backend-common/src/reading/BitbucketUrlReader.test.ts +++ b/packages/backend-common/src/reading/BitbucketUrlReader.test.ts @@ -104,20 +104,13 @@ describe('BitbucketUrlReader', () => { describe('readTree', () => { const repoBuffer = fs.readFileSync( path.resolve( - 'src', - 'reading', - '__fixtures__', - 'bitbucket-repo-with-commit-hash.tar.gz', + __dirname, + '__fixtures__/bitbucket-repo-with-commit-hash.tar.gz', ), ); const privateBitbucketRepoBuffer = fs.readFileSync( - path.resolve( - 'src', - 'reading', - '__fixtures__', - 'bitbucket-server-repo.tar.gz', - ), + path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'), ); beforeEach(() => { @@ -298,10 +291,8 @@ describe('BitbucketUrlReader', () => { describe('search hosted', () => { const repoBuffer = fs.readFileSync( path.resolve( - 'src', - 'reading', - '__fixtures__', - 'bitbucket-repo-with-commit-hash.tar.gz', + __dirname, + '__fixtures__/bitbucket-repo-with-commit-hash.tar.gz', ), ); @@ -386,12 +377,7 @@ describe('BitbucketUrlReader', () => { describe('search private', () => { const privateBitbucketRepoBuffer = fs.readFileSync( - path.resolve( - 'src', - 'reading', - '__fixtures__', - 'bitbucket-server-repo.tar.gz', - ), + path.resolve(__dirname, '__fixtures__/bitbucket-server-repo.tar.gz'), ); beforeEach(() => { diff --git a/packages/backend-common/src/reading/GithubUrlReader.test.ts b/packages/backend-common/src/reading/GithubUrlReader.test.ts index f9717a862a..e70444cf2c 100644 --- a/packages/backend-common/src/reading/GithubUrlReader.test.ts +++ b/packages/backend-common/src/reading/GithubUrlReader.test.ts @@ -254,12 +254,7 @@ describe('GithubUrlReader', () => { describe('readTree', () => { const repoBuffer = fs.readFileSync( - path.resolve( - 'src', - 'reading', - '__fixtures__', - 'backstage-mock-etag123.tar.gz', - ), + path.resolve(__dirname, '__fixtures__/backstage-mock-etag123.tar.gz'), ); const reposGithubApiResponse = { @@ -540,12 +535,7 @@ describe('GithubUrlReader', () => { describe('search', () => { const repoBuffer = fs.readFileSync( - path.resolve( - 'src', - 'reading', - '__fixtures__', - 'backstage-mock-etag123.tar.gz', - ), + path.resolve(__dirname, '__fixtures__/backstage-mock-etag123.tar.gz'), ); const githubTreeContents: GhTreeResponse['tree'] = [ diff --git a/packages/backend-common/src/reading/GitlabUrlReader.test.ts b/packages/backend-common/src/reading/GitlabUrlReader.test.ts index 51b211e698..331150bde3 100644 --- a/packages/backend-common/src/reading/GitlabUrlReader.test.ts +++ b/packages/backend-common/src/reading/GitlabUrlReader.test.ts @@ -223,7 +223,7 @@ describe('GitlabUrlReader', () => { describe('readTree', () => { const archiveBuffer = fs.readFileSync( - path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.tar.gz'), + path.resolve(__dirname, '__fixtures__/gitlab-archive.tar.gz'), ); const projectGitlabApiResponse = { @@ -495,7 +495,7 @@ describe('GitlabUrlReader', () => { describe('search', () => { const archiveBuffer = fs.readFileSync( - path.resolve('src', 'reading', '__fixtures__', 'gitlab-archive.tar.gz'), + path.resolve(__dirname, '__fixtures__/gitlab-archive.tar.gz'), ); const projectGitlabApiResponse = { diff --git a/packages/cli-common/src/paths.test.ts b/packages/cli-common/src/paths.test.ts index 894060f2e8..5c1cf8af08 100644 --- a/packages/cli-common/src/paths.test.ts +++ b/packages/cli-common/src/paths.test.ts @@ -46,6 +46,8 @@ describe('paths', () => { const dir = resolvePath(__dirname, '..'); const root = resolvePath(__dirname, '../../..'); + jest.spyOn(process, 'cwd').mockReturnValue(dir); + const paths = findPaths(__dirname); expect(paths.ownDir).toBe(dir); diff --git a/packages/cli/config/eslint.backend.js b/packages/cli/config/eslint.backend.js index 99767f5d79..a97f26f8da 100644 --- a/packages/cli/config/eslint.backend.js +++ b/packages/cli/config/eslint.backend.js @@ -14,6 +14,15 @@ * limitations under the License. */ +const globalRestrictedSyntax = [ + { + message: + 'Default import from winston is not allowed, import `* as winston` instead.', + selector: + 'ImportDeclaration[source.value="winston"] ImportDefaultSpecifier', + }, +]; + module.exports = { extends: [ '@spotify/eslint-config-base', @@ -69,17 +78,12 @@ module.exports = { // Avoid default import from winston as it breaks at runtime 'no-restricted-syntax': [ 'error', - { - message: - 'Default import from winston is not allowed, import `* as winston` instead.', - selector: - 'ImportDeclaration[source.value="winston"] ImportDefaultSpecifier', - }, { message: "`__dirname` doesn't refer to the same dir in production builds, try `resolvePackagePath()` from `@backstage/backend-common` instead.", selector: 'Identifier[name="__dirname"]', }, + ...globalRestrictedSyntax, ], }, overrides: [ @@ -103,6 +107,7 @@ module.exports = { bundledDependencies: true, }, ], + 'no-restricted-syntax': ['error', ...globalRestrictedSyntax], }, }, ], diff --git a/packages/cli/config/jest.js b/packages/cli/config/jest.js index 80b3e84cda..c687616a7d 100644 --- a/packages/cli/config/jest.js +++ b/packages/cli/config/jest.js @@ -18,7 +18,7 @@ const fs = require('fs-extra'); const path = require('path'); const glob = require('util').promisify(require('glob')); -async function getProjectConfig(targetPath) { +async function getProjectConfig(targetPath, displayName) { const configJsPath = path.resolve(targetPath, 'jest.config.js'); const configTsPath = path.resolve(targetPath, 'jest.config.ts'); // If the package has it's own jest config, we use that instead. @@ -73,6 +73,7 @@ async function getProjectConfig(targetPath) { const transformModulePattern = transformModules && `(?!${transformModules})`; const options = { + displayName, rootDir: path.resolve(targetPath, 'src'), coverageDirectory: path.resolve(targetPath, 'coverage'), collectCoverageFrom: ['**/*.{js,jsx,ts,tsx}', '!**/*.d.ts'], @@ -143,7 +144,7 @@ async function getRootConfig() { const packageData = await fs.readJson(packagePath); const testScript = packageData.scripts && packageData.scripts.test; if (testScript && testScript.includes('backstage-cli test')) { - return await getProjectConfig(projectPath); + return await getProjectConfig(projectPath, packageData.name); } return undefined; diff --git a/packages/core-app-api/src/app/AppThemeProvider.tsx b/packages/core-app-api/src/app/AppThemeProvider.tsx index 4e283a1d00..4e3a8487a6 100644 --- a/packages/core-app-api/src/app/AppThemeProvider.tsx +++ b/packages/core-app-api/src/app/AppThemeProvider.tsx @@ -15,7 +15,8 @@ */ import React, { useMemo, useEffect, useState, PropsWithChildren } from 'react'; -import { ThemeProvider, CssBaseline } from '@material-ui/core'; +import { ThemeProvider } from '@material-ui/core/styles'; +import CssBaseline from '@material-ui/core/CssBaseline'; import { useApi, appThemeApiRef, AppTheme } from '@backstage/core-plugin-api'; import { useObservable } from 'react-use'; diff --git a/packages/core-components/.eslintrc.js b/packages/core-components/.eslintrc.js index d592a653c8..65a93d3660 100644 --- a/packages/core-components/.eslintrc.js +++ b/packages/core-components/.eslintrc.js @@ -1,8 +1,25 @@ +const base = require('@backstage/cli/config/eslint'); +const [, baseRestrictedImports] = base.rules['no-restricted-imports']; + module.exports = { extends: [require.resolve('@backstage/cli/config/eslint')], rules: { // TODO: add prop types to JS and remove 'react/prop-types': 0, 'jest/expect-expect': 0, + 'no-restricted-imports': [ + 2, + { + ...baseRestrictedImports, + paths: [ + { + // Importing the entire MUI icons packages kills build performance as the list of icons is huge. + name: '@material-ui/core', + message: "Please import '@material-ui/core/...' instead.", + }, + ...baseRestrictedImports.paths, + ], + }, + ], }, }; diff --git a/packages/core-components/api-report.md b/packages/core-components/api-report.md index 235e11607f..38fe19fc8b 100644 --- a/packages/core-components/api-report.md +++ b/packages/core-components/api-report.md @@ -8,9 +8,8 @@ import { ApiRef } from '@backstage/core-plugin-api'; import { BackstageIdentityApi } from '@backstage/core-plugin-api'; import { BackstageTheme } from '@backstage/theme'; -import { Breadcrumbs as Breadcrumbs_2 } from '@material-ui/core'; -import { ButtonProps as ButtonProps_2 } from '@material-ui/core'; -import { CardHeaderProps } from '@material-ui/core'; +import { ButtonProps as ButtonProps_2 } from '@material-ui/core/Button'; +import { CardHeaderProps } from '@material-ui/core/CardHeader'; import { Column } from '@material-table/core'; import { ComponentClass } from 'react'; import { ComponentProps } from 'react'; @@ -20,9 +19,10 @@ import { CSSProperties } from 'react'; import { ElementType } from 'react'; import { ErrorInfo } from 'react'; import { IconComponent } from '@backstage/core-plugin-api'; -import { LinearProgressProps } from '@material-ui/core'; -import { LinkProps as LinkProps_2 } from '@material-ui/core'; +import { LinearProgressProps } from '@material-ui/core/LinearProgress'; +import { LinkProps as LinkProps_2 } from '@material-ui/core/Link'; import { LinkProps as LinkProps_3 } from 'react-router-dom'; +import MaterialBreadcrumbs from '@material-ui/core/Breadcrumbs'; import { MaterialTableProps } from '@material-table/core'; import { NavLinkProps } from 'react-router-dom'; import { Overrides } from '@material-ui/core/styles/overrides'; @@ -36,14 +36,14 @@ import { SessionApi } from '@backstage/core-plugin-api'; import { SignInPageProps } from '@backstage/core-plugin-api'; import { SparklinesLineProps } from 'react-sparklines'; import { SparklinesProps } from 'react-sparklines'; -import { StyledComponentProps } from '@material-ui/core'; +import { StyledComponentProps } from '@material-ui/core/styles'; import { StyleRules } from '@material-ui/styles'; import { StyleRules as StyleRules_2 } from '@material-ui/core/styles/withStyles'; -import { TabProps } from '@material-ui/core'; +import { TabProps } from '@material-ui/core/Tab'; import { TextTruncateProps } from 'react-text-truncate'; -import { Theme } from '@material-ui/core'; -import { TooltipProps } from '@material-ui/core'; -import { WithStyles } from '@material-ui/core'; +import { Theme } from '@material-ui/core/styles'; +import { TooltipProps } from '@material-ui/core/Tooltip'; +import { WithStyles } from '@material-ui/core/styles'; // Warning: (ae-missing-release-tag) "AlertDisplay" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // diff --git a/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx b/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx index f43dbd08dd..3a7ec392ee 100644 --- a/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx +++ b/packages/core-components/src/components/AlertDisplay/AlertDisplay.tsx @@ -15,7 +15,8 @@ */ import React, { useEffect, useState } from 'react'; -import { Snackbar, IconButton } from '@material-ui/core'; +import Snackbar from '@material-ui/core/Snackbar'; +import IconButton from '@material-ui/core/IconButton'; import CloseIcon from '@material-ui/icons/Close'; import { Alert } from '@material-ui/lab'; import { AlertMessage, useApi, alertApiRef } from '@backstage/core-plugin-api'; diff --git a/packages/core-components/src/components/Avatar/Avatar.tsx b/packages/core-components/src/components/Avatar/Avatar.tsx index 0156c58b92..32ce92b46b 100644 --- a/packages/core-components/src/components/Avatar/Avatar.tsx +++ b/packages/core-components/src/components/Avatar/Avatar.tsx @@ -14,12 +14,8 @@ * limitations under the License. */ import React, { CSSProperties } from 'react'; -import { - Avatar as MaterialAvatar, - createStyles, - makeStyles, - Theme, -} from '@material-ui/core'; +import { createStyles, makeStyles, Theme } from '@material-ui/core/styles'; +import MaterialAvatar from '@material-ui/core/Avatar'; import { extractInitials, stringToColor } from './utils'; export type AvatarClassKey = 'avatar'; diff --git a/packages/core-components/src/components/Button/Button.stories.tsx b/packages/core-components/src/components/Button/Button.stories.tsx index 3451a77765..32c3a98bcc 100644 --- a/packages/core-components/src/components/Button/Button.stories.tsx +++ b/packages/core-components/src/components/Button/Button.stories.tsx @@ -17,15 +17,13 @@ import React, { ComponentType } from 'react'; import { Button } from './Button'; import { useLocation } from 'react-router-dom'; import { createRouteRef, useRouteRef } from '@backstage/core-plugin-api'; -import { - Divider, - Link, - List, - ListItem, - ListItemText, - Typography, - Button as MaterialButton, -} from '@material-ui/core'; +import Divider from '@material-ui/core/Divider'; +import Link from '@material-ui/core/Link'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; +import Typography from '@material-ui/core/Typography'; +import MaterialButton from '@material-ui/core/Button'; import { wrapInTestApp } from '@backstage/test-utils'; const routeRef = createRouteRef({ diff --git a/packages/core-components/src/components/Button/Button.tsx b/packages/core-components/src/components/Button/Button.tsx index bfbd6d7a3c..d5c59c3169 100644 --- a/packages/core-components/src/components/Button/Button.tsx +++ b/packages/core-components/src/components/Button/Button.tsx @@ -14,10 +14,9 @@ * limitations under the License. */ -import { - Button as MaterialButton, +import MaterialButton, { ButtonProps as MaterialButtonProps, -} from '@material-ui/core'; +} from '@material-ui/core/Button'; import React from 'react'; import { Link, LinkProps } from '../Link'; diff --git a/packages/core-components/src/components/Chip/Chip.stories.tsx b/packages/core-components/src/components/Chip/Chip.stories.tsx index ff52a81c16..f5cdfd3f16 100644 --- a/packages/core-components/src/components/Chip/Chip.stories.tsx +++ b/packages/core-components/src/components/Chip/Chip.stories.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { Chip } from '@material-ui/core'; +import Chip from '@material-ui/core/Chip'; export default { title: 'Data Display/Chip', diff --git a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx index 3ce041a819..3aa2f42984 100644 --- a/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx +++ b/packages/core-components/src/components/CodeSnippet/CodeSnippet.tsx @@ -14,12 +14,56 @@ * limitations under the License. */ -import React from 'react'; -import SyntaxHighlighter from 'react-syntax-highlighter'; -import { docco, dark } from 'react-syntax-highlighter/dist/cjs/styles/hljs'; -import { useTheme } from '@material-ui/core'; +import React, { lazy, Suspense } from 'react'; +import { useTheme } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; import { CopyTextButton } from '../CopyTextButton'; +import { Progress } from '../Progress'; + +const LazySyntaxHighlighter = lazy(async () => { + const [{ default: SyntaxHighlighter }, { docco, dark }] = await Promise.all([ + import('react-syntax-highlighter'), + import('react-syntax-highlighter/dist/cjs/styles/hljs'), + ]); + + function LazyHighlighter(props: CodeSnippetProps) { + const { + text, + language, + showLineNumbers = false, + highlightedNumbers, + customStyle, + } = props; + const theme = useTheme(); + const mode = theme.palette.type === 'dark' ? dark : docco; + const highlightColor = + theme.palette.type === 'dark' ? '#256bf3' : '#e6ffed'; + + return ( + + highlightedNumbers?.includes(lineNumber) + ? { + style: { + backgroundColor: highlightColor, + }, + } + : {} + } + > + {text} + + ); + } + + return { default: LazyHighlighter }; +}); /** * Properties for {@link CodeSnippet} @@ -68,38 +112,12 @@ export interface CodeSnippetProps { * providing consistent theming and copy code button */ export function CodeSnippet(props: CodeSnippetProps) { - const { - text, - language, - showLineNumbers = false, - showCopyCodeButton = false, - highlightedNumbers, - customStyle, - } = props; - const theme = useTheme(); - const mode = theme.palette.type === 'dark' ? dark : docco; - const highlightColor = theme.palette.type === 'dark' ? '#256bf3' : '#e6ffed'; + const { text, showCopyCodeButton = false } = props; return (
- - highlightedNumbers?.includes(lineNumber) - ? { - style: { - backgroundColor: highlightColor, - }, - } - : {} - } - > - {text} - + }> + + {showCopyCodeButton && (
diff --git a/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx b/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx index 2d2fb4006a..3986b8fa43 100644 --- a/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx +++ b/packages/core-components/src/components/CopyTextButton/CopyTextButton.tsx @@ -15,7 +15,8 @@ */ import { errorApiRef, useApi } from '@backstage/core-plugin-api'; -import { IconButton, Tooltip } from '@material-ui/core'; +import IconButton from '@material-ui/core/IconButton'; +import Tooltip from '@material-ui/core/Tooltip'; import CopyIcon from '@material-ui/icons/FileCopy'; import React, { MouseEventHandler, useEffect, useState } from 'react'; import { useCopyToClipboard } from 'react-use'; diff --git a/packages/core-components/src/components/CreateButton/CreateButton.tsx b/packages/core-components/src/components/CreateButton/CreateButton.tsx index c6b9b7abed..074ee9fc9f 100644 --- a/packages/core-components/src/components/CreateButton/CreateButton.tsx +++ b/packages/core-components/src/components/CreateButton/CreateButton.tsx @@ -15,7 +15,9 @@ */ import { BackstageTheme } from '@backstage/theme'; -import { Button, IconButton, useMediaQuery } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import IconButton from '@material-ui/core/IconButton'; +import useMediaQuery from '@material-ui/core/useMediaQuery'; import React from 'react'; import { Link as RouterLink, LinkProps } from 'react-router-dom'; import AddCircleOutline from '@material-ui/icons/AddCircleOutline'; diff --git a/packages/core-components/src/components/Dialog/Dialog.stories.tsx b/packages/core-components/src/components/Dialog/Dialog.stories.tsx index b4c0a7da57..200124ce9d 100644 --- a/packages/core-components/src/components/Dialog/Dialog.stories.tsx +++ b/packages/core-components/src/components/Dialog/Dialog.stories.tsx @@ -14,15 +14,13 @@ * limitations under the License. */ -import { - Button, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - IconButton, - Typography, -} from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import IconButton from '@material-ui/core/IconButton'; +import Typography from '@material-ui/core/Typography'; import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; import CloseIcon from '@material-ui/icons/Close'; import React, { useState } from 'react'; diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx index 583413eb35..a64514be61 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.stories.tsx @@ -16,7 +16,8 @@ import React from 'react'; import { DismissableBanner } from './DismissableBanner'; -import { Link, Typography } from '@material-ui/core'; +import Link from '@material-ui/core/Link'; +import Typography from '@material-ui/core/Typography'; import { ApiProvider, ApiRegistry, WebStorage } from '@backstage/core-app-api'; import { ErrorApi, diff --git a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx index 3d229a5d54..be8e613b61 100644 --- a/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx +++ b/packages/core-components/src/components/DismissableBanner/DismissableBanner.tsx @@ -18,7 +18,7 @@ import React, { ReactNode, useState, useEffect } from 'react'; import { useApi, storageApiRef } from '@backstage/core-plugin-api'; import { useObservable } from 'react-use'; import classNames from 'classnames'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; import Snackbar from '@material-ui/core/Snackbar'; import SnackbarContent from '@material-ui/core/SnackbarContent'; diff --git a/packages/core-components/src/components/Drawer/Drawer.stories.tsx b/packages/core-components/src/components/Drawer/Drawer.stories.tsx index 2538af855e..7e1c8a728f 100644 --- a/packages/core-components/src/components/Drawer/Drawer.stories.tsx +++ b/packages/core-components/src/components/Drawer/Drawer.stories.tsx @@ -15,15 +15,11 @@ */ import React, { useState } from 'react'; -import { - Drawer, - Button, - Typography, - makeStyles, - IconButton, - createStyles, - Theme, -} from '@material-ui/core'; +import { makeStyles, createStyles, Theme } from '@material-ui/core/styles'; +import Drawer from '@material-ui/core/Drawer'; +import Button from '@material-ui/core/Button'; +import Typography from '@material-ui/core/Typography'; +import IconButton from '@material-ui/core/IconButton'; import Close from '@material-ui/icons/Close'; export default { diff --git a/packages/core-components/src/components/EmptyState/EmptyState.stories.tsx b/packages/core-components/src/components/EmptyState/EmptyState.stories.tsx index ed4dbe2101..53314497fb 100644 --- a/packages/core-components/src/components/EmptyState/EmptyState.stories.tsx +++ b/packages/core-components/src/components/EmptyState/EmptyState.stories.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { EmptyState } from './EmptyState'; -import { Button } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; import { MissingAnnotationEmptyState } from './MissingAnnotationEmptyState'; export default { diff --git a/packages/core-components/src/components/EmptyState/EmptyState.test.tsx b/packages/core-components/src/components/EmptyState/EmptyState.test.tsx index 2f4e4e883d..620e8d4d31 100644 --- a/packages/core-components/src/components/EmptyState/EmptyState.test.tsx +++ b/packages/core-components/src/components/EmptyState/EmptyState.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { EmptyState } from './EmptyState'; import { renderWithEffects, wrapInTestApp } from '@backstage/test-utils'; -import { Button } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; describe('', () => { it('render EmptyState component with type annotaion is missing', async () => { diff --git a/packages/core-components/src/components/EmptyState/EmptyState.tsx b/packages/core-components/src/components/EmptyState/EmptyState.tsx index f3fc3b2399..a7298c4192 100644 --- a/packages/core-components/src/components/EmptyState/EmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/EmptyState.tsx @@ -15,7 +15,9 @@ */ import React from 'react'; -import { makeStyles, Typography, Grid } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import Grid from '@material-ui/core/Grid'; import { EmptyStateImage } from './EmptyStateImage'; export type EmptyStateClassKey = 'root' | 'action' | 'imageContainer'; diff --git a/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx b/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx index 012fb04e76..f82d8e6e57 100644 --- a/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx +++ b/packages/core-components/src/components/EmptyState/EmptyStateImage.tsx @@ -19,7 +19,7 @@ import missingAnnotation from './assets/missingAnnotation.svg'; import noInformation from './assets/noInformation.svg'; import createComponent from './assets/createComponent.svg'; import noBuild from './assets/noBuild.svg'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; type Props = { missing: 'field' | 'info' | 'content' | 'data'; diff --git a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx index 6f20f7c8e6..61131bad9b 100644 --- a/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx +++ b/packages/core-components/src/components/EmptyState/MissingAnnotationEmptyState.tsx @@ -15,7 +15,9 @@ */ import React from 'react'; -import { Button, makeStyles, Typography } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Button from '@material-ui/core/Button'; +import Typography from '@material-ui/core/Typography'; import { BackstageTheme } from '@backstage/theme'; import { Link } from '../Link'; import { EmptyState } from './EmptyState'; diff --git a/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx b/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx index 22f28a7a73..3ef35d6eaa 100644 --- a/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx +++ b/packages/core-components/src/components/ErrorPanel/ErrorPanel.tsx @@ -14,7 +14,10 @@ * limitations under the License. */ -import { List, ListItem, ListItemText, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; import React, { PropsWithChildren } from 'react'; import { CopyTextButton } from '../CopyTextButton'; import { WarningPanel } from '../WarningPanel'; diff --git a/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx b/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx index 7c4b9736b7..3152d701c8 100644 --- a/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx +++ b/packages/core-components/src/components/FeatureDiscovery/FeatureCalloutCircular.tsx @@ -14,7 +14,9 @@ * limitations under the License. */ -import { ClickAwayListener, makeStyles, Typography } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import ClickAwayListener from '@material-ui/core/ClickAwayListener'; +import Typography from '@material-ui/core/Typography'; import React, { PropsWithChildren, useCallback, diff --git a/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx b/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx index c4508eb9bc..4e83976a96 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx +++ b/packages/core-components/src/components/HeaderIconLinkRow/HeaderIconLinkRow.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import { IconLinkVertical, IconLinkVerticalProps } from './IconLinkVertical'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; export type HeaderIconLinkRowClassKey = 'links'; diff --git a/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx b/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx index 532ba2f959..421147753b 100644 --- a/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx +++ b/packages/core-components/src/components/HeaderIconLinkRow/IconLinkVertical.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; import classnames from 'classnames'; -import { makeStyles, Link } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Link from '@material-ui/core/Link'; import LinkIcon from '@material-ui/icons/Link'; import { Link as RouterLink } from '../Link'; diff --git a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.test.tsx b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.test.tsx index 080e48919b..a3ef93d9fa 100644 --- a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.test.tsx +++ b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.test.tsx @@ -18,7 +18,7 @@ import React from 'react'; import { fireEvent } from '@testing-library/react'; import { renderInTestApp } from '@backstage/test-utils'; import { HorizontalScrollGrid } from './HorizontalScrollGrid'; -import { Grid } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; describe('', () => { beforeEach(() => { diff --git a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx index 88b61d56bb..483d27d657 100644 --- a/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx +++ b/packages/core-components/src/components/HorizontalScrollGrid/HorizontalScrollGrid.tsx @@ -18,7 +18,9 @@ import React, { PropsWithChildren } from 'react'; import classNames from 'classnames'; import ChevronLeftIcon from '@material-ui/icons/ChevronLeft'; import ChevronRightIcon from '@material-ui/icons/ChevronRight'; -import { Grid, IconButton, makeStyles, Theme } from '@material-ui/core'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import Grid from '@material-ui/core/Grid'; +import IconButton from '@material-ui/core/IconButton'; const generateGradientStops = (themeType: 'dark' | 'light') => { // 97% corresponds to the theme.palette.background.default for the light theme diff --git a/packages/core-components/src/components/Lifecycle/Lifecycle.tsx b/packages/core-components/src/components/Lifecycle/Lifecycle.tsx index 76e63854f5..f553129927 100644 --- a/packages/core-components/src/components/Lifecycle/Lifecycle.tsx +++ b/packages/core-components/src/components/Lifecycle/Lifecycle.tsx @@ -16,7 +16,7 @@ import React from 'react'; import CSS from 'csstype'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; type Props = CSS.Properties & { shorthand?: boolean; diff --git a/packages/core-components/src/components/Link/Link.tsx b/packages/core-components/src/components/Link/Link.tsx index d20773a8bb..8866150f86 100644 --- a/packages/core-components/src/components/Link/Link.tsx +++ b/packages/core-components/src/components/Link/Link.tsx @@ -15,10 +15,9 @@ */ import { useAnalytics } from '@backstage/core-plugin-api'; -import { - Link as MaterialLink, +import MaterialLink, { LinkProps as MaterialLinkProps, -} from '@material-ui/core'; +} from '@material-ui/core/Link'; import React, { ElementType } from 'react'; import { Link as RouterLink, diff --git a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx index 65be789bb4..eacd9adc8a 100644 --- a/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx +++ b/packages/core-components/src/components/MarkdownContent/MarkdownContent.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import ReactMarkdown from 'react-markdown'; import gfm from 'remark-gfm'; import React from 'react'; diff --git a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx index 7f7f51abba..b911a9a1d9 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/LoginRequestListItem.tsx @@ -14,15 +14,12 @@ * limitations under the License. */ -import { - ListItem, - ListItemAvatar, - ListItemText, - makeStyles, - Typography, - Theme, - Button, -} from '@material-ui/core'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemAvatar from '@material-ui/core/ListItemAvatar'; +import ListItemText from '@material-ui/core/ListItemText'; +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; import React, { useState } from 'react'; import { PendingAuthRequest } from '@backstage/core-plugin-api'; diff --git a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx index 73e276fce9..5378fa6c15 100644 --- a/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx +++ b/packages/core-components/src/components/OAuthRequestDialog/OAuthRequestDialog.tsx @@ -14,16 +14,13 @@ * limitations under the License. */ -import { - Dialog, - DialogActions, - DialogContent, - DialogTitle, - List, - makeStyles, - Theme, - Button, -} from '@material-ui/core'; +import { makeStyles, Theme } from '@material-ui/core/styles'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import DialogContent from '@material-ui/core/DialogContent'; +import DialogTitle from '@material-ui/core/DialogTitle'; +import List from '@material-ui/core/List'; +import Button from '@material-ui/core/Button'; import React, { useMemo, useState } from 'react'; import { useObservable } from 'react-use'; import LoginRequestListItem from './LoginRequestListItem'; diff --git a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.stories.tsx b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.stories.tsx index 0882a63e9c..a022b3b5c2 100644 --- a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.stories.tsx +++ b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.stories.tsx @@ -13,7 +13,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Box } from '@material-ui/core'; +import Box from '@material-ui/core/Box'; import React from 'react'; import { OverflowTooltip } from './OverflowTooltip'; diff --git a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx index a06930cdfa..fb21813f89 100644 --- a/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx +++ b/packages/core-components/src/components/OverflowTooltip/OverflowTooltip.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ -import { makeStyles, Tooltip, TooltipProps } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Tooltip, { TooltipProps } from '@material-ui/core/Tooltip'; import React, { useState } from 'react'; import TextTruncate, { TextTruncateProps } from 'react-text-truncate'; diff --git a/packages/core-components/src/components/Progress/Progress.tsx b/packages/core-components/src/components/Progress/Progress.tsx index 00ad532b5e..f199c5640f 100644 --- a/packages/core-components/src/components/Progress/Progress.tsx +++ b/packages/core-components/src/components/Progress/Progress.tsx @@ -15,7 +15,9 @@ */ import React, { useState, useEffect, PropsWithChildren } from 'react'; -import { LinearProgress, LinearProgressProps } from '@material-ui/core'; +import LinearProgress, { + LinearProgressProps, +} from '@material-ui/core/LinearProgress'; export function Progress(props: PropsWithChildren) { const [isVisible, setIsVisible] = useState(false); diff --git a/packages/core-components/src/components/ProgressBars/Gauge.tsx b/packages/core-components/src/components/ProgressBars/Gauge.tsx index 2699f8a289..2f6973e4d8 100644 --- a/packages/core-components/src/components/ProgressBars/Gauge.tsx +++ b/packages/core-components/src/components/ProgressBars/Gauge.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles, useTheme } from '@material-ui/core'; +import { makeStyles, useTheme } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; import { Circle } from 'rc-progress'; import React from 'react'; diff --git a/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx b/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx index da81100a99..ad3323f8d3 100644 --- a/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx +++ b/packages/core-components/src/components/ProgressBars/GaugeCard.stories.tsx @@ -16,7 +16,7 @@ import React, { PropsWithChildren } from 'react'; import { GaugeCard } from './GaugeCard'; -import { Grid } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; import { MemoryRouter } from 'react-router'; const linkInfo = { title: 'Go to XYZ Location', link: '#' }; diff --git a/packages/core-components/src/components/ProgressBars/GaugeCard.tsx b/packages/core-components/src/components/ProgressBars/GaugeCard.tsx index aec63add11..5c5a825921 100644 --- a/packages/core-components/src/components/ProgressBars/GaugeCard.tsx +++ b/packages/core-components/src/components/ProgressBars/GaugeCard.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import { InfoCard, InfoCardVariants } from '../../layout/InfoCard'; import { BottomLinkProps } from '../../layout/BottomLink'; import { Gauge } from './Gauge'; diff --git a/packages/core-components/src/components/ProgressBars/LinearGauge.tsx b/packages/core-components/src/components/ProgressBars/LinearGauge.tsx index cf8c022852..afc93fd337 100644 --- a/packages/core-components/src/components/ProgressBars/LinearGauge.tsx +++ b/packages/core-components/src/components/ProgressBars/LinearGauge.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; -import { Tooltip, useTheme } from '@material-ui/core'; +import { useTheme } from '@material-ui/core/styles'; +import Tooltip from '@material-ui/core/Tooltip'; // @ts-ignore import { Line } from 'rc-progress'; import { BackstageTheme } from '@backstage/theme'; diff --git a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx index 37143000a3..68d7360400 100644 --- a/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx +++ b/packages/core-components/src/components/ResponseErrorPanel/ResponseErrorPanel.tsx @@ -15,7 +15,10 @@ */ import { ResponseError } from '@backstage/errors'; -import { Divider, ListItem, ListItemText, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Divider from '@material-ui/core/Divider'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemText from '@material-ui/core/ListItemText'; import React from 'react'; import { CodeSnippet } from '../CodeSnippet'; import { CopyTextButton } from '../CopyTextButton'; diff --git a/packages/core-components/src/components/Select/Select.tsx b/packages/core-components/src/components/Select/Select.tsx index 23ed2cf62c..a0e3aba94b 100644 --- a/packages/core-components/src/components/Select/Select.tsx +++ b/packages/core-components/src/components/Select/Select.tsx @@ -14,16 +14,14 @@ * limitations under the License. */ -import { - Checkbox, - Chip, - ClickAwayListener, - FormControl, - InputBase, - MenuItem, - Select, - Typography, -} from '@material-ui/core'; +import Checkbox from '@material-ui/core/Checkbox'; +import Chip from '@material-ui/core/Chip'; +import ClickAwayListener from '@material-ui/core/ClickAwayListener'; +import FormControl from '@material-ui/core/FormControl'; +import InputBase from '@material-ui/core/InputBase'; +import MenuItem from '@material-ui/core/MenuItem'; +import Select from '@material-ui/core/Select'; +import Typography from '@material-ui/core/Typography'; import { createStyles, makeStyles, diff --git a/packages/core-components/src/components/Select/static/ClosedDropdown.tsx b/packages/core-components/src/components/Select/static/ClosedDropdown.tsx index 61a24abcef..eb93f5a354 100644 --- a/packages/core-components/src/components/Select/static/ClosedDropdown.tsx +++ b/packages/core-components/src/components/Select/static/ClosedDropdown.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ import React from 'react'; -import { SvgIcon, makeStyles, createStyles } from '@material-ui/core'; +import { makeStyles, createStyles } from '@material-ui/core/styles'; +import SvgIcon from '@material-ui/core/SvgIcon'; export type ClosedDropdownClassKey = 'icon'; diff --git a/packages/core-components/src/components/Select/static/OpenedDropdown.tsx b/packages/core-components/src/components/Select/static/OpenedDropdown.tsx index eb86a34fe0..617288ded6 100644 --- a/packages/core-components/src/components/Select/static/OpenedDropdown.tsx +++ b/packages/core-components/src/components/Select/static/OpenedDropdown.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ import React from 'react'; -import { SvgIcon, makeStyles, createStyles } from '@material-ui/core'; +import { makeStyles, createStyles } from '@material-ui/core/styles'; +import SvgIcon from '@material-ui/core/SvgIcon'; export type OpenedDropdownClassKey = 'icon'; diff --git a/packages/core-components/src/components/SimpleStepper/SimpleStepper.stories.tsx b/packages/core-components/src/components/SimpleStepper/SimpleStepper.stories.tsx index 9d958f766d..aa6846bc8f 100644 --- a/packages/core-components/src/components/SimpleStepper/SimpleStepper.stories.tsx +++ b/packages/core-components/src/components/SimpleStepper/SimpleStepper.stories.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { TextField } from '@material-ui/core'; +import TextField from '@material-ui/core/TextField'; import React, { useState } from 'react'; import { SimpleStepper } from './SimpleStepper'; import { SimpleStepperStep } from './SimpleStepperStep'; diff --git a/packages/core-components/src/components/SimpleStepper/SimpleStepper.tsx b/packages/core-components/src/components/SimpleStepper/SimpleStepper.tsx index 9ffb63c085..4a1a4ab919 100644 --- a/packages/core-components/src/components/SimpleStepper/SimpleStepper.tsx +++ b/packages/core-components/src/components/SimpleStepper/SimpleStepper.tsx @@ -20,7 +20,7 @@ import React, { useEffect, PropsWithChildren, } from 'react'; -import { Stepper as MuiStepper } from '@material-ui/core'; +import MuiStepper from '@material-ui/core/Stepper'; type InternalState = { stepperLength: number; diff --git a/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx b/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx index 270099a104..5f4bdbf0c6 100644 --- a/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx +++ b/packages/core-components/src/components/SimpleStepper/SimpleStepperFooter.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ import React, { useContext, ReactNode, PropsWithChildren } from 'react'; -import { Button, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Button from '@material-ui/core/Button'; import { StepActions } from './types'; import { VerticalStepperContext } from './SimpleStepper'; diff --git a/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx b/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx index 0696a1256a..bb46163105 100644 --- a/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx +++ b/packages/core-components/src/components/SimpleStepper/SimpleStepperStep.tsx @@ -14,13 +14,11 @@ * limitations under the License. */ import React, { PropsWithChildren } from 'react'; -import { - Step as MuiStep, - StepContent, - StepLabel, - Typography, - makeStyles, -} from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import MuiStep from '@material-ui/core/Step'; +import StepContent from '@material-ui/core/StepContent'; +import StepLabel from '@material-ui/core/StepLabel'; +import Typography from '@material-ui/core/Typography'; import { SimpleStepperFooter } from './SimpleStepperFooter'; import { StepProps } from './types'; diff --git a/packages/core-components/src/components/Status/Status.tsx b/packages/core-components/src/components/Status/Status.tsx index a6215d6127..a855fe3ebe 100644 --- a/packages/core-components/src/components/Status/Status.tsx +++ b/packages/core-components/src/components/Status/Status.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; import classNames from 'classnames'; import React, { PropsWithChildren } from 'react'; diff --git a/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx index 3c869f88c3..2f5dc0b6b5 100644 --- a/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx +++ b/packages/core-components/src/components/StructuredMetadataTable/MetadataTable.tsx @@ -16,15 +16,15 @@ import React from 'react'; import { - Table, - TableBody, - TableCell, - TableRow, withStyles, createStyles, WithStyles, Theme, -} from '@material-ui/core'; +} from '@material-ui/core/styles'; +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableRow from '@material-ui/core/TableRow'; export type MetadataTableTitleCellClassKey = 'root'; diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.stories.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.stories.tsx index 458c431b27..f48e959073 100644 --- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.stories.tsx +++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.stories.tsx @@ -15,7 +15,7 @@ */ import React, { PropsWithChildren } from 'react'; import { InfoCard } from '../../layout/InfoCard'; -import { Grid } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; import { StructuredMetadataTable } from './StructuredMetadataTable'; const cardContentStyle = { heightX: 200, width: 500 }; diff --git a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx index abaa662159..9ef7890820 100644 --- a/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx +++ b/packages/core-components/src/components/StructuredMetadataTable/StructuredMetadataTable.tsx @@ -15,7 +15,12 @@ */ import React, { Fragment, ReactElement } from 'react'; -import { withStyles, createStyles, WithStyles, Theme } from '@material-ui/core'; +import { + withStyles, + createStyles, + WithStyles, + Theme, +} from '@material-ui/core/styles'; import startCase from 'lodash/startCase'; import { diff --git a/packages/core-components/src/components/SupportButton/SupportButton.tsx b/packages/core-components/src/components/SupportButton/SupportButton.tsx index bee2928314..841bfe9429 100644 --- a/packages/core-components/src/components/SupportButton/SupportButton.tsx +++ b/packages/core-components/src/components/SupportButton/SupportButton.tsx @@ -16,20 +16,18 @@ import { useApp } from '@backstage/core-plugin-api'; import { BackstageTheme } from '@backstage/theme'; -import { - Box, - Button, - DialogActions, - IconButton, - List, - ListItem, - ListItemIcon, - ListItemText, - makeStyles, - Popover, - Typography, - useMediaQuery, -} from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import useMediaQuery from '@material-ui/core/useMediaQuery'; +import Box from '@material-ui/core/Box'; +import Button from '@material-ui/core/Button'; +import DialogActions from '@material-ui/core/DialogActions'; +import IconButton from '@material-ui/core/IconButton'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemText from '@material-ui/core/ListItemText'; +import Popover from '@material-ui/core/Popover'; +import Typography from '@material-ui/core/Typography'; import React, { MouseEventHandler, useState } from 'react'; import { SupportItem, SupportItemLink, useSupportConfig } from '../../hooks'; import { HelpIcon } from '../../icons'; diff --git a/packages/core-components/src/components/TabbedLayout/TabbedLayout.tsx b/packages/core-components/src/components/TabbedLayout/TabbedLayout.tsx index 03f012b78f..26e70e33b5 100644 --- a/packages/core-components/src/components/TabbedLayout/TabbedLayout.tsx +++ b/packages/core-components/src/components/TabbedLayout/TabbedLayout.tsx @@ -23,7 +23,7 @@ import React, { ReactNode, } from 'react'; import { RoutedTabs } from './RoutedTabs'; -import { TabProps } from '@material-ui/core'; +import { TabProps } from '@material-ui/core/Tab'; type SubRoute = { path: string; diff --git a/packages/core-components/src/components/TabbedLayout/types.ts b/packages/core-components/src/components/TabbedLayout/types.ts index b70ab3da0a..59e26305bd 100644 --- a/packages/core-components/src/components/TabbedLayout/types.ts +++ b/packages/core-components/src/components/TabbedLayout/types.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { TabProps } from '@material-ui/core'; +import { TabProps } from '@material-ui/core/Tab'; import * as React from 'react'; export type SubRoute = { diff --git a/packages/core-components/src/components/Table/Filters.tsx b/packages/core-components/src/components/Table/Filters.tsx index 7498138751..0f4143d442 100644 --- a/packages/core-components/src/components/Table/Filters.tsx +++ b/packages/core-components/src/components/Table/Filters.tsx @@ -16,7 +16,8 @@ import React, { useEffect, useState } from 'react'; import { BackstageTheme } from '@backstage/theme'; -import { Button, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Button from '@material-ui/core/Button'; import { Select } from '../Select'; import { SelectProps } from '../Select/Select'; diff --git a/packages/core-components/src/components/Table/SubvalueCell.tsx b/packages/core-components/src/components/Table/SubvalueCell.tsx index 43fb54fca8..2564e8e4eb 100644 --- a/packages/core-components/src/components/Table/SubvalueCell.tsx +++ b/packages/core-components/src/components/Table/SubvalueCell.tsx @@ -16,7 +16,7 @@ import React from 'react'; import { BackstageTheme } from '@backstage/theme'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; export type SubvalueCellClassKey = 'value' | 'subvalue'; diff --git a/packages/core-components/src/components/Table/Table.stories.tsx b/packages/core-components/src/components/Table/Table.stories.tsx index 27fd33f32c..7785764b22 100644 --- a/packages/core-components/src/components/Table/Table.stories.tsx +++ b/packages/core-components/src/components/Table/Table.stories.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; import { Link } from '../Link'; import { SubvalueCell, Table, TableColumn } from '.'; diff --git a/packages/core-components/src/components/Table/Table.tsx b/packages/core-components/src/components/Table/Table.tsx index 61e9cc7969..f61811938e 100644 --- a/packages/core-components/src/components/Table/Table.tsx +++ b/packages/core-components/src/components/Table/Table.tsx @@ -15,13 +15,9 @@ */ import { BackstageTheme } from '@backstage/theme'; -import { - IconButton, - makeStyles, - Typography, - useTheme, - withStyles, -} from '@material-ui/core'; +import { makeStyles, useTheme, withStyles } from '@material-ui/core/styles'; +import IconButton from '@material-ui/core/IconButton'; +import Typography from '@material-ui/core/Typography'; // Material-table is not using the standard icons available in in material-ui. https://github.com/mbrn/material-table/issues/51 import AddBox from '@material-ui/icons/AddBox'; import ArrowUpward from '@material-ui/icons/ArrowUpward'; diff --git a/packages/core-components/src/components/Tabs/Tab.tsx b/packages/core-components/src/components/Tabs/Tab.tsx index 7b284940f1..571640d970 100644 --- a/packages/core-components/src/components/Tabs/Tab.tsx +++ b/packages/core-components/src/components/Tabs/Tab.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; -import { Tab, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Tab from '@material-ui/core/Tab'; import { BackstageTheme } from '@backstage/theme'; interface StyledTabProps { diff --git a/packages/core-components/src/components/Tabs/TabBar.tsx b/packages/core-components/src/components/Tabs/TabBar.tsx index d0febebc6a..d2f0250fd4 100644 --- a/packages/core-components/src/components/Tabs/TabBar.tsx +++ b/packages/core-components/src/components/Tabs/TabBar.tsx @@ -15,7 +15,8 @@ */ import React, { PropsWithChildren } from 'react'; -import { Tabs, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Tabs from '@material-ui/core/Tabs'; import { BackstageTheme } from '@backstage/theme'; interface StyledTabsProps { diff --git a/packages/core-components/src/components/Tabs/TabIcon.tsx b/packages/core-components/src/components/Tabs/TabIcon.tsx index 37b38217a3..9743469aa7 100644 --- a/packages/core-components/src/components/Tabs/TabIcon.tsx +++ b/packages/core-components/src/components/Tabs/TabIcon.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; -import { IconButton, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import IconButton from '@material-ui/core/IconButton'; import { BackstageTheme } from '@backstage/theme'; interface StyledIconProps { diff --git a/packages/core-components/src/components/Tabs/Tabs.tsx b/packages/core-components/src/components/Tabs/Tabs.tsx index d60f3ff639..31bf1d2027 100644 --- a/packages/core-components/src/components/Tabs/Tabs.tsx +++ b/packages/core-components/src/components/Tabs/Tabs.tsx @@ -16,7 +16,7 @@ import React, { useRef, useEffect, MutableRefObject, useState } from 'react'; import { BackstageTheme } from '@backstage/theme'; -import { AppBar } from '@material-ui/core'; +import AppBar from '@material-ui/core/AppBar'; import { makeStyles } from '@material-ui/core/styles'; import NavigateBeforeIcon from '@material-ui/icons/NavigateBefore'; import NavigateNextIcon from '@material-ui/icons/NavigateNext'; diff --git a/packages/core-components/src/components/TrendLine/TrendLine.tsx b/packages/core-components/src/components/TrendLine/TrendLine.tsx index cb44d2b36b..b59d748c2c 100644 --- a/packages/core-components/src/components/TrendLine/TrendLine.tsx +++ b/packages/core-components/src/components/TrendLine/TrendLine.tsx @@ -21,7 +21,7 @@ import { SparklinesLineProps, SparklinesProps, } from 'react-sparklines'; -import { useTheme } from '@material-ui/core'; +import { useTheme } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; function color(data: number[], theme: BackstageTheme): string | undefined { diff --git a/packages/core-components/src/components/WarningPanel/WarningPanel.stories.tsx b/packages/core-components/src/components/WarningPanel/WarningPanel.stories.tsx index bab831e905..838cb02a76 100644 --- a/packages/core-components/src/components/WarningPanel/WarningPanel.stories.tsx +++ b/packages/core-components/src/components/WarningPanel/WarningPanel.stories.tsx @@ -16,7 +16,9 @@ import React from 'react'; import { WarningPanel } from './WarningPanel'; -import { Button, Link, Typography } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import Link from '@material-ui/core/Link'; +import Typography from '@material-ui/core/Typography'; export default { title: 'Feedback/Warning Panel', diff --git a/packages/core-components/src/components/WarningPanel/WarningPanel.test.tsx b/packages/core-components/src/components/WarningPanel/WarningPanel.test.tsx index 4ae6423333..25cf642c28 100644 --- a/packages/core-components/src/components/WarningPanel/WarningPanel.test.tsx +++ b/packages/core-components/src/components/WarningPanel/WarningPanel.test.tsx @@ -17,7 +17,7 @@ import React from 'react'; import { fireEvent, screen } from '@testing-library/react'; import { renderInTestApp } from '@backstage/test-utils'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; import { WarningPanel, WarningProps } from './WarningPanel'; diff --git a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx index bf845617c9..0cf250497b 100644 --- a/packages/core-components/src/components/WarningPanel/WarningPanel.tsx +++ b/packages/core-components/src/components/WarningPanel/WarningPanel.tsx @@ -14,16 +14,12 @@ * limitations under the License. */ import { BackstageTheme } from '@backstage/theme'; -import { - Accordion, - AccordionSummary, - AccordionDetails, - Grid, - makeStyles, - Typography, - darken, - lighten, -} from '@material-ui/core'; +import { makeStyles, darken, lighten } from '@material-ui/core/styles'; +import Accordion from '@material-ui/core/Accordion'; +import AccordionSummary from '@material-ui/core/AccordionSummary'; +import AccordionDetails from '@material-ui/core/AccordionDetails'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; import ErrorOutline from '@material-ui/icons/ErrorOutline'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import React from 'react'; diff --git a/packages/core-components/src/layout/BottomLink/BottomLink.tsx b/packages/core-components/src/layout/BottomLink/BottomLink.tsx index cb168600e5..e097724385 100644 --- a/packages/core-components/src/layout/BottomLink/BottomLink.tsx +++ b/packages/core-components/src/layout/BottomLink/BottomLink.tsx @@ -15,7 +15,9 @@ */ import React from 'react'; -import { Divider, Typography, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Divider from '@material-ui/core/Divider'; +import Typography from '@material-ui/core/Typography'; import ArrowIcon from '@material-ui/icons/ArrowForward'; import { BackstageTheme } from '@backstage/theme'; import Box from '@material-ui/core/Box'; diff --git a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.stories.tsx b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.stories.tsx index 9716471d9f..12bd757aa3 100644 --- a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.stories.tsx +++ b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.stories.tsx @@ -13,7 +13,12 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Box, List, ListItem, Popover, Typography } from '@material-ui/core'; + +import Box from '@material-ui/core/Box'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import Popover from '@material-ui/core/Popover'; +import Typography from '@material-ui/core/Typography'; import ExpandLessIcon from '@material-ui/icons/ExpandLess'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import React, { Fragment } from 'react'; diff --git a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.test.tsx b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.test.tsx index 4c8d707501..12125bafc9 100644 --- a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.test.tsx +++ b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.test.tsx @@ -15,7 +15,7 @@ */ import { renderInTestApp } from '@backstage/test-utils'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; import { fireEvent } from '@testing-library/react'; import React from 'react'; import { Link } from '../../components/Link'; diff --git a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx index 26304f9e2b..4423c5c0b7 100644 --- a/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx +++ b/packages/core-components/src/layout/Breadcrumbs/Breadcrumbs.tsx @@ -14,15 +14,13 @@ * limitations under the License. */ -import { - Box, - Breadcrumbs as MaterialBreadcrumbs, - List, - ListItem, - Popover, - Typography, - withStyles, -} from '@material-ui/core'; +import { withStyles } from '@material-ui/core/styles'; +import Box from '@material-ui/core/Box'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import Popover from '@material-ui/core/Popover'; +import Typography from '@material-ui/core/Typography'; +import MaterialBreadcrumbs from '@material-ui/core/Breadcrumbs'; import React, { ComponentProps, Fragment } from 'react'; type Props = ComponentProps; diff --git a/packages/core-components/src/layout/Content/Content.tsx b/packages/core-components/src/layout/Content/Content.tsx index 588c9fd630..122eb07e2a 100644 --- a/packages/core-components/src/layout/Content/Content.tsx +++ b/packages/core-components/src/layout/Content/Content.tsx @@ -16,7 +16,7 @@ import React, { PropsWithChildren } from 'react'; import classNames from 'classnames'; -import { Theme, makeStyles } from '@material-ui/core'; +import { Theme, makeStyles } from '@material-ui/core/styles'; export type BackstageContentClassKey = 'root' | 'stretch' | 'noPadding'; diff --git a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx index c3faec64a2..b4a80ac4b1 100644 --- a/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx +++ b/packages/core-components/src/layout/ContentHeader/ContentHeader.tsx @@ -19,7 +19,8 @@ */ import React, { PropsWithChildren, ReactNode } from 'react'; -import { Typography, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; import { Helmet } from 'react-helmet'; export type ContentHeaderClassKey = diff --git a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx index 79aaaebfc6..46257f85bb 100644 --- a/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx +++ b/packages/core-components/src/layout/ErrorPage/ErrorPage.tsx @@ -15,7 +15,9 @@ */ import React from 'react'; -import { Typography, Link, Grid } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import Link from '@material-ui/core/Link'; +import Grid from '@material-ui/core/Grid'; import { makeStyles } from '@material-ui/core/styles'; import { BackstageTheme } from '@backstage/theme'; import { MicDrop } from './MicDrop'; diff --git a/packages/core-components/src/layout/ErrorPage/MicDrop.tsx b/packages/core-components/src/layout/ErrorPage/MicDrop.tsx index 5500994e4f..efa101b23b 100644 --- a/packages/core-components/src/layout/ErrorPage/MicDrop.tsx +++ b/packages/core-components/src/layout/ErrorPage/MicDrop.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import MicDropSvgUrl from './mic-drop.svg'; const useStyles = makeStyles( diff --git a/packages/core-components/src/layout/Header/Header.tsx b/packages/core-components/src/layout/Header/Header.tsx index 535e3c4ed8..aed9e9f8e4 100644 --- a/packages/core-components/src/layout/Header/Header.tsx +++ b/packages/core-components/src/layout/Header/Header.tsx @@ -16,7 +16,11 @@ import { useApi, configApiRef } from '@backstage/core-plugin-api'; import { BackstageTheme } from '@backstage/theme'; -import { Box, Grid, makeStyles, Tooltip, Typography } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Box from '@material-ui/core/Box'; +import Grid from '@material-ui/core/Grid'; +import Tooltip from '@material-ui/core/Tooltip'; +import Typography from '@material-ui/core/Typography'; import React, { CSSProperties, PropsWithChildren, ReactNode } from 'react'; import { Helmet } from 'react-helmet'; import { Link } from '../../components/Link'; diff --git a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx index 5243a65498..d8dc398ce3 100644 --- a/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx +++ b/packages/core-components/src/layout/HeaderActionMenu/HeaderActionMenu.tsx @@ -15,15 +15,14 @@ */ import React, { Fragment, ReactElement, ComponentType } from 'react'; -import { - IconButton, - List, - ListItem, - ListItemIcon, - ListItemText, - Popover, +import IconButton from '@material-ui/core/IconButton'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemText, { ListItemTextProps, -} from '@material-ui/core'; +} from '@material-ui/core/ListItemText'; +import Popover from '@material-ui/core/Popover'; import { VerticalMenuIcon } from './VerticalMenuIcon'; type ActionItemProps = { diff --git a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx index 5071971f48..3b9bde0f62 100644 --- a/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx +++ b/packages/core-components/src/layout/HeaderLabel/HeaderLabel.tsx @@ -14,7 +14,10 @@ * limitations under the License. */ -import { Link, makeStyles, Typography, Grid } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Link from '@material-ui/core/Link'; +import Typography from '@material-ui/core/Typography'; +import Grid from '@material-ui/core/Grid'; import React from 'react'; export type HeaderLabelClassKey = 'root' | 'label' | 'value'; diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx index e6762de90e..2501785701 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.test.tsx @@ -17,7 +17,8 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; import { HeaderTabs } from '.'; -import { Badge, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Badge from '@material-ui/core/Badge'; const mockTabs = [ { id: 'overview', label: 'Overview' }, diff --git a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx index b34af3eb83..dd740d1c53 100644 --- a/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx +++ b/packages/core-components/src/layout/HeaderTabs/HeaderTabs.tsx @@ -18,7 +18,9 @@ // This is just a temporary solution to implementing tabs for now import React, { useState, useEffect } from 'react'; -import { makeStyles, Tabs, Tab as TabUI, TabProps } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import TabUI, { TabProps } from '@material-ui/core/Tab'; +import Tabs from '@material-ui/core/Tabs'; export type HeaderTabsClassKey = | 'tabsWrapper' diff --git a/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx b/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx index eda877884e..1d4bf6954a 100644 --- a/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx +++ b/packages/core-components/src/layout/HomepageTimer/HomepageTimer.test.tsx @@ -18,7 +18,7 @@ import { renderWithEffects } from '@backstage/test-utils'; import { HomepageTimer } from './HomepageTimer'; import React from 'react'; import { lightTheme } from '@backstage/theme'; -import { ThemeProvider } from '@material-ui/core'; +import { ThemeProvider } from '@material-ui/core/styles'; import { ApiProvider, ApiRegistry, diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.stories.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.stories.tsx index cf012a129a..8dd8272f5a 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.stories.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.stories.tsx @@ -13,7 +13,9 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Grid, Typography } from '@material-ui/core'; + +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; import React, { PropsWithChildren } from 'react'; import { MemoryRouter } from 'react-router'; import { InfoCard } from './InfoCard'; diff --git a/packages/core-components/src/layout/InfoCard/InfoCard.tsx b/packages/core-components/src/layout/InfoCard/InfoCard.tsx index a3094b792e..0b9c4c7dcf 100644 --- a/packages/core-components/src/layout/InfoCard/InfoCard.tsx +++ b/packages/core-components/src/layout/InfoCard/InfoCard.tsx @@ -15,16 +15,12 @@ */ import React, { ReactNode } from 'react'; -import { - Card, - CardActions, - CardContent, - CardHeader, - CardHeaderProps, - Divider, - withStyles, - makeStyles, -} from '@material-ui/core'; +import { withStyles, makeStyles } from '@material-ui/core/styles'; +import Card from '@material-ui/core/Card'; +import CardActions from '@material-ui/core/CardActions'; +import CardContent from '@material-ui/core/CardContent'; +import CardHeader, { CardHeaderProps } from '@material-ui/core/CardHeader'; +import Divider from '@material-ui/core/Divider'; import classNames from 'classnames'; import { ErrorBoundary, ErrorBoundaryProps } from '../ErrorBoundary'; import { BottomLink, BottomLinkProps } from '../BottomLink'; diff --git a/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx b/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx index 7cd67ff00d..1d336fc5f5 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCard.stories.tsx @@ -14,14 +14,12 @@ * limitations under the License. */ -import { - Card, - CardActions, - CardContent, - CardMedia, - makeStyles, - Typography, -} from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Card from '@material-ui/core/Card'; +import CardActions from '@material-ui/core/CardActions'; +import CardContent from '@material-ui/core/CardContent'; +import CardMedia from '@material-ui/core/CardMedia'; +import Typography from '@material-ui/core/Typography'; import React from 'react'; import { MemoryRouter } from 'react-router'; import { Button } from '../../components'; diff --git a/packages/core-components/src/layout/ItemCard/ItemCard.tsx b/packages/core-components/src/layout/ItemCard/ItemCard.tsx index 81a88d2c09..82426c14e1 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCard.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCard.tsx @@ -13,14 +13,13 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { - Box, - Card, - CardActions, - CardContent, - CardMedia, - Chip, -} from '@material-ui/core'; + +import Box from '@material-ui/core/Box'; +import Card from '@material-ui/core/Card'; +import CardActions from '@material-ui/core/CardActions'; +import CardContent from '@material-ui/core/CardContent'; +import CardMedia from '@material-ui/core/CardMedia'; +import Chip from '@material-ui/core/Chip'; import React, { ReactNode } from 'react'; import { Button } from '../../components'; import { ItemCardHeader } from './ItemCardHeader'; diff --git a/packages/core-components/src/layout/ItemCard/ItemCardGrid.test.tsx b/packages/core-components/src/layout/ItemCard/ItemCardGrid.test.tsx index 30fdb415e5..f8759ffd17 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardGrid.test.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardGrid.test.tsx @@ -15,7 +15,7 @@ */ import { renderInTestApp } from '@backstage/test-utils'; -import { Card } from '@material-ui/core'; +import Card from '@material-ui/core/Card'; import { screen } from '@testing-library/react'; import React from 'react'; import { ItemCardGrid } from './ItemCardGrid'; diff --git a/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx b/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx index 739398252e..b4fe504c31 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardGrid.tsx @@ -14,7 +14,12 @@ * limitations under the License. */ -import { createStyles, makeStyles, Theme, WithStyles } from '@material-ui/core'; +import { + createStyles, + makeStyles, + Theme, + WithStyles, +} from '@material-ui/core/styles'; import React from 'react'; export type ItemCardGridClassKey = 'root'; diff --git a/packages/core-components/src/layout/ItemCard/ItemCardHeader.test.tsx b/packages/core-components/src/layout/ItemCard/ItemCardHeader.test.tsx index 41b150a900..a401dfb4a5 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardHeader.test.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardHeader.test.tsx @@ -15,7 +15,8 @@ */ import { renderInTestApp } from '@backstage/test-utils'; -import { Card, CardMedia } from '@material-ui/core'; +import Card from '@material-ui/core/Card'; +import CardMedia from '@material-ui/core/CardMedia'; import { screen } from '@testing-library/react'; import React from 'react'; import { ItemCardHeader } from './ItemCardHeader'; diff --git a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx index 7ad6732e02..c604f24e3f 100644 --- a/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx +++ b/packages/core-components/src/layout/ItemCard/ItemCardHeader.tsx @@ -14,12 +14,8 @@ * limitations under the License. */ -import { - createStyles, - makeStyles, - Typography, - WithStyles, -} from '@material-ui/core'; +import { createStyles, makeStyles, WithStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; import React from 'react'; import { BackstageTheme } from '@backstage/theme'; diff --git a/packages/core-components/src/layout/Page/Page.stories.tsx b/packages/core-components/src/layout/Page/Page.stories.tsx index 3ad9ecfe72..7386d198a3 100644 --- a/packages/core-components/src/layout/Page/Page.stories.tsx +++ b/packages/core-components/src/layout/Page/Page.stories.tsx @@ -14,7 +14,11 @@ * limitations under the License. */ -import { Box, Chip, Grid, Link, Typography } from '@material-ui/core'; +import Box from '@material-ui/core/Box'; +import Chip from '@material-ui/core/Chip'; +import Grid from '@material-ui/core/Grid'; +import Link from '@material-ui/core/Link'; +import Typography from '@material-ui/core/Typography'; import React, { useState } from 'react'; import { MemoryRouter } from 'react-router'; import { createApp } from '@backstage/core-app-api'; diff --git a/packages/core-components/src/layout/Page/Page.tsx b/packages/core-components/src/layout/Page/Page.tsx index 37d6c663f2..57653d23b5 100644 --- a/packages/core-components/src/layout/Page/Page.tsx +++ b/packages/core-components/src/layout/Page/Page.tsx @@ -16,7 +16,7 @@ import React, { PropsWithChildren } from 'react'; import { BackstageTheme } from '@backstage/theme'; -import { makeStyles, ThemeProvider } from '@material-ui/core'; +import { makeStyles, ThemeProvider } from '@material-ui/core/styles'; export type PageClassKey = 'root'; diff --git a/packages/core-components/src/layout/Sidebar/Bar.tsx b/packages/core-components/src/layout/Sidebar/Bar.tsx index 750ec6bbdc..e6fa3820ad 100644 --- a/packages/core-components/src/layout/Sidebar/Bar.tsx +++ b/packages/core-components/src/layout/Sidebar/Bar.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ -import { makeStyles, useMediaQuery } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import useMediaQuery from '@material-ui/core/useMediaQuery'; import clsx from 'clsx'; import React, { useRef, useState, useContext, PropsWithChildren } from 'react'; import { sidebarConfig, SidebarContext } from './config'; diff --git a/packages/core-components/src/layout/Sidebar/Intro.tsx b/packages/core-components/src/layout/Sidebar/Intro.tsx index 70b952588d..8086898e64 100644 --- a/packages/core-components/src/layout/Sidebar/Intro.tsx +++ b/packages/core-components/src/layout/Sidebar/Intro.tsx @@ -16,7 +16,10 @@ import React, { useContext, useState } from 'react'; import { useLocalStorage } from 'react-use'; -import { Link, Typography, makeStyles, Collapse } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Link from '@material-ui/core/Link'; +import Typography from '@material-ui/core/Typography'; +import Collapse from '@material-ui/core/Collapse'; import CloseIcon from '@material-ui/icons/Close'; import { BackstageTheme } from '@backstage/theme'; import { diff --git a/packages/core-components/src/layout/Sidebar/Items.test.tsx b/packages/core-components/src/layout/Sidebar/Items.test.tsx index 89d2a2c294..123c30ceae 100644 --- a/packages/core-components/src/layout/Sidebar/Items.test.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.test.tsx @@ -16,14 +16,14 @@ import React from 'react'; import { renderInTestApp } from '@backstage/test-utils'; -import { screen } from '@testing-library/react'; +import { createEvent, fireEvent, screen } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; import HomeIcon from '@material-ui/icons/Home'; import CreateComponentIcon from '@material-ui/icons/AddCircleOutline'; import { Sidebar } from './Bar'; -import { SidebarItem } from './Items'; +import { SidebarItem, SidebarSearchField } from './Items'; import { renderHook } from '@testing-library/react-hooks'; -import { hexToRgb, makeStyles } from '@material-ui/core'; +import { hexToRgb, makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles({ spotlight: { @@ -36,6 +36,7 @@ async function renderSidebar() { await renderInTestApp( + {}} to="/search" /> { ).toHaveStyle(`background-color: ${hexToRgb('2b2a2a')}`); }); }); + describe('SidebarSearchField', () => { + it('should be defaultPrevented when enter is pressed', async () => { + const searchEvent = createEvent.keyDown( + await screen.findByPlaceholderText('Search'), + { key: 'Enter', code: 'Enter', charCode: 13 }, + ); + fireEvent(await screen.findByPlaceholderText('Search'), searchEvent); + expect(searchEvent.defaultPrevented).toBeTruthy(); + }); + }); }); diff --git a/packages/core-components/src/layout/Sidebar/Items.tsx b/packages/core-components/src/layout/Sidebar/Items.tsx index 8bd80b6825..883e0395cd 100644 --- a/packages/core-components/src/layout/Sidebar/Items.tsx +++ b/packages/core-components/src/layout/Sidebar/Items.tsx @@ -16,14 +16,10 @@ import { IconComponent } from '@backstage/core-plugin-api'; import { BackstageTheme } from '@backstage/theme'; -import { - Badge, - makeStyles, - styled, - TextField, - Theme, - Typography, -} from '@material-ui/core'; +import { makeStyles, styled, Theme } from '@material-ui/core/styles'; +import Badge from '@material-ui/core/Badge'; +import TextField from '@material-ui/core/TextField'; +import Typography from '@material-ui/core/Typography'; import { CreateCSSProperties } from '@material-ui/core/styles/withStyles'; import SearchIcon from '@material-ui/icons/Search'; import clsx from 'clsx'; @@ -310,6 +306,7 @@ export function SidebarSearchField(props: SidebarSearchFieldProps) { const handleEnter: KeyboardEventHandler = ev => { if (ev.key === 'Enter') { + ev.preventDefault(); search(); } }; diff --git a/packages/core-components/src/layout/Sidebar/Page.tsx b/packages/core-components/src/layout/Sidebar/Page.tsx index c375112321..cc50c5af6b 100644 --- a/packages/core-components/src/layout/Sidebar/Page.tsx +++ b/packages/core-components/src/layout/Sidebar/Page.tsx @@ -14,7 +14,7 @@ * limitations under the License. */ -import { makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; import React, { createContext, PropsWithChildren, diff --git a/packages/core-components/src/layout/SignInPage/SignInPage.tsx b/packages/core-components/src/layout/SignInPage/SignInPage.tsx index 910fc6a7bf..bd4fe37480 100644 --- a/packages/core-components/src/layout/SignInPage/SignInPage.tsx +++ b/packages/core-components/src/layout/SignInPage/SignInPage.tsx @@ -20,7 +20,9 @@ import { SignInPageProps, useApi, } from '@backstage/core-plugin-api'; -import { Button, Grid, Typography } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; import React, { useState } from 'react'; import { useMount } from 'react-use'; import { Progress } from '../../components/Progress'; diff --git a/packages/core-components/src/layout/SignInPage/auth0Provider.tsx b/packages/core-components/src/layout/SignInPage/auth0Provider.tsx index 78043cb3fb..19836827c9 100644 --- a/packages/core-components/src/layout/SignInPage/auth0Provider.tsx +++ b/packages/core-components/src/layout/SignInPage/auth0Provider.tsx @@ -15,7 +15,9 @@ */ import React from 'react'; -import { Grid, Typography, Button } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; import { InfoCard } from '../InfoCard/InfoCard'; import { ProviderComponent, ProviderLoader, SignInProvider } from './types'; import { diff --git a/packages/core-components/src/layout/SignInPage/commonProvider.tsx b/packages/core-components/src/layout/SignInPage/commonProvider.tsx index 3160bd171b..8df5faf34e 100644 --- a/packages/core-components/src/layout/SignInPage/commonProvider.tsx +++ b/packages/core-components/src/layout/SignInPage/commonProvider.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; -import { Typography, Button } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; import { InfoCard } from '../InfoCard/InfoCard'; import { ProviderComponent, diff --git a/packages/core-components/src/layout/SignInPage/customProvider.tsx b/packages/core-components/src/layout/SignInPage/customProvider.tsx index 46fed6b5ae..3be375ed3d 100644 --- a/packages/core-components/src/layout/SignInPage/customProvider.tsx +++ b/packages/core-components/src/layout/SignInPage/customProvider.tsx @@ -16,14 +16,12 @@ import React from 'react'; import { useForm, UseFormRegisterReturn } from 'react-hook-form'; -import { - Typography, - Button, - FormControl, - TextField, - FormHelperText, - makeStyles, -} from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; +import FormControl from '@material-ui/core/FormControl'; +import TextField from '@material-ui/core/TextField'; +import FormHelperText from '@material-ui/core/FormHelperText'; import isEmpty from 'lodash/isEmpty'; import { InfoCard } from '../InfoCard/InfoCard'; import { ProviderComponent, ProviderLoader, SignInProvider } from './types'; diff --git a/packages/core-components/src/layout/SignInPage/guestProvider.tsx b/packages/core-components/src/layout/SignInPage/guestProvider.tsx index 8673c17ffa..e91d9cbc75 100644 --- a/packages/core-components/src/layout/SignInPage/guestProvider.tsx +++ b/packages/core-components/src/layout/SignInPage/guestProvider.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; -import { Typography, Button } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import Button from '@material-ui/core/Button'; import { InfoCard } from '../InfoCard/InfoCard'; import { GridItem } from './styles'; import { ProviderComponent, ProviderLoader, SignInProvider } from './types'; diff --git a/packages/core-components/src/layout/SignInPage/styles.tsx b/packages/core-components/src/layout/SignInPage/styles.tsx index 55db36229b..6cf5ded226 100644 --- a/packages/core-components/src/layout/SignInPage/styles.tsx +++ b/packages/core-components/src/layout/SignInPage/styles.tsx @@ -14,7 +14,8 @@ * limitations under the License. */ import React from 'react'; -import { Grid, makeStyles } from '@material-ui/core'; +import { makeStyles } from '@material-ui/core/styles'; +import Grid from '@material-ui/core/Grid'; export type SignInPageClassKey = 'container' | 'item'; diff --git a/packages/core-components/src/layout/TabbedCard/TabbedCard.stories.tsx b/packages/core-components/src/layout/TabbedCard/TabbedCard.stories.tsx index 3214d26653..77fff64fb5 100644 --- a/packages/core-components/src/layout/TabbedCard/TabbedCard.stories.tsx +++ b/packages/core-components/src/layout/TabbedCard/TabbedCard.stories.tsx @@ -13,7 +13,8 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { Grid } from '@material-ui/core'; + +import Grid from '@material-ui/core/Grid'; import React, { PropsWithChildren, useState } from 'react'; import { MemoryRouter } from 'react-router'; import { CardTab, TabbedCard } from './TabbedCard'; diff --git a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx index e9905663b2..f9ec755e00 100644 --- a/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx +++ b/packages/core-components/src/layout/TabbedCard/TabbedCard.tsx @@ -20,17 +20,13 @@ import React, { ReactNode, PropsWithChildren, } from 'react'; -import { - Card, - CardContent, - CardHeader, - Divider, - withStyles, - makeStyles, - Tabs, - Tab, - TabProps, -} from '@material-ui/core'; +import { withStyles, makeStyles } from '@material-ui/core/styles'; +import Card from '@material-ui/core/Card'; +import CardContent from '@material-ui/core/CardContent'; +import CardHeader from '@material-ui/core/CardHeader'; +import Divider from '@material-ui/core/Divider'; +import Tabs from '@material-ui/core/Tabs'; +import Tab, { TabProps } from '@material-ui/core/Tab'; import { BottomLink, BottomLinkProps } from '../BottomLink'; import { ErrorBoundary, ErrorBoundaryProps } from '../ErrorBoundary'; diff --git a/packages/integration/src/azure/config.test.ts b/packages/integration/src/azure/config.test.ts index 385086fbcf..353065a030 100644 --- a/packages/integration/src/azure/config.test.ts +++ b/packages/integration/src/azure/config.test.ts @@ -31,15 +31,17 @@ describe('readAzureIntegrationConfig', () => { data: Partial, ): Promise { const fullSchema = await loadConfigSchema({ - dependencies: [require('../../package.json').name], + dependencies: ['@backstage/integration'], }); const serializedSchema = fullSchema.serialize() as { - schemas: { path: string }[]; + schemas: { value: { properties?: { integrations?: object } } }[]; }; const schema = await loadConfigSchema({ serialized: { - ...serializedSchema, // grab the schema from this package only - schemas: serializedSchema.schemas.filter(s => s.path === 'config.d.ts'), + ...serializedSchema, // only include schemas that apply to integrations + schemas: serializedSchema.schemas.filter( + s => s.value?.properties?.integrations, + ), }, }); const processed = schema.process( diff --git a/packages/integration/src/bitbucket/config.test.ts b/packages/integration/src/bitbucket/config.test.ts index b887566e35..5440b174c8 100644 --- a/packages/integration/src/bitbucket/config.test.ts +++ b/packages/integration/src/bitbucket/config.test.ts @@ -31,15 +31,17 @@ describe('readBitbucketIntegrationConfig', () => { data: Partial, ): Promise { const fullSchema = await loadConfigSchema({ - dependencies: [require('../../package.json').name], + dependencies: ['@backstage/integration'], }); const serializedSchema = fullSchema.serialize() as { - schemas: { path: string }[]; + schemas: { value: { properties?: { integrations?: object } } }[]; }; const schema = await loadConfigSchema({ serialized: { - ...serializedSchema, // grab the schema from this package only - schemas: serializedSchema.schemas.filter(s => s.path === 'config.d.ts'), + ...serializedSchema, // only include schemas that apply to integrations + schemas: serializedSchema.schemas.filter( + s => s.value?.properties?.integrations, + ), }, }); const processed = schema.process( diff --git a/packages/integration/src/github/config.test.ts b/packages/integration/src/github/config.test.ts index eb084b14a9..73efb4f81a 100644 --- a/packages/integration/src/github/config.test.ts +++ b/packages/integration/src/github/config.test.ts @@ -31,15 +31,17 @@ describe('readGitHubIntegrationConfig', () => { data: Partial, ): Promise { const fullSchema = await loadConfigSchema({ - dependencies: [require('../../package.json').name], + dependencies: ['@backstage/integration'], }); const serializedSchema = fullSchema.serialize() as { - schemas: { path: string }[]; + schemas: { value: { properties?: { integrations?: object } } }[]; }; const schema = await loadConfigSchema({ serialized: { - ...serializedSchema, // grab the schema from this package only - schemas: serializedSchema.schemas.filter(s => s.path === 'config.d.ts'), + ...serializedSchema, // only include schemas that apply to integrations + schemas: serializedSchema.schemas.filter( + s => s.value?.properties?.integrations, + ), }, }); const processed = schema.process( diff --git a/packages/integration/src/gitlab/config.test.ts b/packages/integration/src/gitlab/config.test.ts index 1308704e9d..db03285206 100644 --- a/packages/integration/src/gitlab/config.test.ts +++ b/packages/integration/src/gitlab/config.test.ts @@ -31,15 +31,17 @@ describe('readGitLabIntegrationConfig', () => { data: Partial, ): Promise { const fullSchema = await loadConfigSchema({ - dependencies: [require('../../package.json').name], + dependencies: ['@backstage/integration'], }); const serializedSchema = fullSchema.serialize() as { - schemas: { path: string }[]; + schemas: { value: { properties?: { integrations?: object } } }[]; }; const schema = await loadConfigSchema({ serialized: { - ...serializedSchema, // grab the schema from this package only - schemas: serializedSchema.schemas.filter(s => s.path === 'config.d.ts'), + ...serializedSchema, // only include schemas that apply to integrations + schemas: serializedSchema.schemas.filter( + s => s.value?.properties?.integrations, + ), }, }); const processed = schema.process( diff --git a/packages/theme/src/baseTheme.ts b/packages/theme/src/baseTheme.ts index b2d964c4db..4a45516a55 100644 --- a/packages/theme/src/baseTheme.ts +++ b/packages/theme/src/baseTheme.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { createTheme as createMuiTheme } from '@material-ui/core'; +import { createTheme as createMuiTheme } from '@material-ui/core/styles'; import { darken, lighten } from '@material-ui/core/styles/colorManipulator'; import { Overrides } from '@material-ui/core/styles/overrides'; diff --git a/plugins/api-docs/dev/index.tsx b/plugins/api-docs/dev/index.tsx index e60647e7b9..633a285b98 100644 --- a/plugins/api-docs/dev/index.tsx +++ b/plugins/api-docs/dev/index.tsx @@ -15,29 +15,34 @@ */ import { ApiEntity, Entity } from '@backstage/catalog-model'; +import { Content, Header, Page } from '@backstage/core-components'; import { createDevApp } from '@backstage/dev-utils'; +import { CatalogEntityPage } from '@backstage/plugin-catalog'; import { catalogApiRef, EntityProvider } from '@backstage/plugin-catalog-react'; import React from 'react'; import { apiDocsConfigRef, + apiDocsPlugin, ApiExplorerPage, defaultDefinitionWidgets, EntityApiDefinitionCard, } from '../src'; import asyncapiApiEntity from './asyncapi-example-api.yaml'; import graphqlApiEntity from './graphql-example-api.yaml'; +import invalidLanguageApiEntity from './invalid-language-example-api.yaml'; import openapiApiEntity from './openapi-example-api.yaml'; import otherApiEntity from './other-example-api.yaml'; -import { Content, Header, Page } from '@backstage/core-components'; const mockEntities = [ openapiApiEntity, asyncapiApiEntity, graphqlApiEntity, + invalidLanguageApiEntity, otherApiEntity, ] as unknown as Entity[]; createDevApp() + .registerPlugin(apiDocsPlugin) .registerApi({ api: catalogApiRef, deps: {}, @@ -65,6 +70,7 @@ createDevApp() }; }, }) + .addPage({ element: }) .addPage({ title: 'API Explorer', element: }) .addPage({ title: 'OpenAPI', @@ -105,6 +111,19 @@ createDevApp() ), }) + .addPage({ + title: 'Invalid Language', + element: ( + +
+ + + + + + + ), + }) .addPage({ title: 'Other', element: ( diff --git a/plugins/api-docs/dev/invalid-language-example-api.yaml b/plugins/api-docs/dev/invalid-language-example-api.yaml new file mode 100644 index 0000000000..01b8ae9457 --- /dev/null +++ b/plugins/api-docs/dev/invalid-language-example-api.yaml @@ -0,0 +1,48 @@ +apiVersion: backstage.io/v1alpha1 +kind: API +metadata: + name: hello-world + description: Hello World example for gRPC +spec: + type: my-invalid-language + lifecycle: deprecated + owner: team-c + definition: | + // Copyright 2015 gRPC authors. + // + // 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. + + syntax = "proto3"; + + option java_multiple_files = true; + option java_package = "io.grpc.examples.helloworld"; + option java_outer_classname = "HelloWorldProto"; + option objc_class_prefix = "HLW"; + + package helloworld; + + // The greeting service definition. + service Greeter { + // Sends a greeting + rpc SayHello (HelloRequest) returns (HelloReply) {} + } + + // The request message containing the user's name. + message HelloRequest { + string name = 1; + } + + // The response message containing the greetings + message HelloReply { + string message = 1; + } diff --git a/plugins/api-docs/package.json b/plugins/api-docs/package.json index be3fdf7229..9a89837102 100644 --- a/plugins/api-docs/package.json +++ b/plugins/api-docs/package.json @@ -49,7 +49,7 @@ "react-router": "6.0.0-beta.0", "react-router-dom": "6.0.0-beta.0", "react-use": "^17.2.4", - "swagger-ui-react": "^3.37.2" + "swagger-ui-react": "^4.0.0-rc.3" }, "devDependencies": { "@backstage/cli": "^0.7.15", diff --git a/plugins/azure-devops-backend/api-report.md b/plugins/azure-devops-backend/api-report.md index 4ad2f833d7..74b4ac5b23 100644 --- a/plugins/azure-devops-backend/api-report.md +++ b/plugins/azure-devops-backend/api-report.md @@ -10,6 +10,7 @@ import { Config } from '@backstage/config'; import express from 'express'; import { GitRepository } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { Logger as Logger_2 } from 'winston'; +import { PullRequestStatus } from 'azure-devops-node-api/interfaces/GitInterfaces'; import { WebApi } from 'azure-devops-node-api'; // Warning: (ae-missing-release-tag) "AzureDevOpsApi" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) @@ -28,6 +29,14 @@ export class AzureDevOpsApi { projectName: string, repoName: string, ): Promise; + // Warning: (ae-forgotten-export) The symbol "PullRequestOptions" needs to be exported by the entry point index.d.ts + // + // (undocumented) + getPullRequests( + projectName: string, + repoName: string, + options: PullRequestOptions, + ): Promise; // (undocumented) getRepoBuilds( projectName: string, @@ -41,6 +50,23 @@ export class AzureDevOpsApi { // @public (undocumented) export function createRouter(options: RouterOptions): Promise; +// Warning: (ae-missing-release-tag) "PullRequest" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) +// +// @public (undocumented) +export type PullRequest = { + pullRequestId?: number; + repoName?: string; + title?: string; + uniqueName?: string; + createdBy?: string; + creationDate?: Date; + sourceRefName?: string; + targetRefName?: string; + status?: PullRequestStatus; + isDraft?: boolean; + link: string; +}; + // Warning: (ae-missing-release-tag) "RepoBuild" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) diff --git a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts index 25022b4c02..fd9aa169d5 100644 --- a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts +++ b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.test.ts @@ -13,17 +13,23 @@ * See the License for the specific language governing permissions and * limitations under the License. */ -import { repoBuildFromBuild } from './AzureDevOpsApi'; -import { RepoBuild } from './types'; +import { mappedPullRequest, mappedRepoBuild } from './AzureDevOpsApi'; +import { PullRequest, RepoBuild } from './types'; import { Build, BuildResult, BuildStatus, DefinitionReference, } from 'azure-devops-node-api/interfaces/BuildInterfaces'; +import { + GitPullRequest, + PullRequestStatus, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { GitRepository } from 'azure-devops-node-api/interfaces/TfvcInterfaces'; +import { IdentityRef } from 'azure-devops-node-api/interfaces/common/VSSInterfaces'; describe('AzureDevOpsApi', () => { - describe('repoBuildFromBuild', () => { + describe('mappedRepoBuild', () => { it('should return RepoBuild from Build', () => { const inputBuildDefinition: DefinitionReference = { name: 'My Build Definition', @@ -57,11 +63,11 @@ describe('AzureDevOpsApi', () => { source: 'refs/heads/develop (f4f78b31)', }; - expect(repoBuildFromBuild(inputBuild)).toEqual(outputRepoBuild); + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); }); }); - describe('repoBuildFromBuild with no Build definition name', () => { + describe('mappedRepoBuild with no Build definition name', () => { it('should return RepoBuild with only Build Number for title', () => { const inputLinks: any = { web: { @@ -91,11 +97,11 @@ describe('AzureDevOpsApi', () => { source: 'refs/heads/develop (f4f78b31)', }; - expect(repoBuildFromBuild(inputBuild)).toEqual(outputRepoBuild); + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); }); }); - describe('repoBuildFromBuild with undefined status', () => { + describe('mappedRepoBuild with undefined status', () => { it('should return BuildStatus of None for status', () => { const inputLinks: any = { web: { @@ -125,11 +131,11 @@ describe('AzureDevOpsApi', () => { source: 'refs/heads/develop (f4f78b31)', }; - expect(repoBuildFromBuild(inputBuild)).toEqual(outputRepoBuild); + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); }); }); - describe('repoBuildFromBuild with undefined result', () => { + describe('mappedRepoBuild with undefined result', () => { it('should return BuildResult of None for result', () => { const inputLinks: any = { web: { @@ -159,11 +165,11 @@ describe('AzureDevOpsApi', () => { source: 'refs/heads/develop (f4f78b31)', }; - expect(repoBuildFromBuild(inputBuild)).toEqual(outputRepoBuild); + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); }); }); - describe('repoBuildFromBuild with undefined link', () => { + describe('mappedRepoBuild with undefined link', () => { it('should return empty string for link', () => { const inputBuild: Build = { id: 1, @@ -187,7 +193,53 @@ describe('AzureDevOpsApi', () => { source: 'refs/heads/develop (f4f78b31)', }; - expect(repoBuildFromBuild(inputBuild)).toEqual(outputRepoBuild); + expect(mappedRepoBuild(inputBuild)).toEqual(outputRepoBuild); + }); + }); + + describe('mappedPullRequest', () => { + it('should return PullRequest from GitPullRequest', () => { + const inputGitRepository: GitRepository = { + name: 'super-feature-repo', + }; + + const inputIdentityRef: IdentityRef = { + displayName: 'Jane Doe', + uniqueName: 'DOMAINjdoe', + }; + + const inputPullRequest: GitPullRequest = { + pullRequestId: 7181, + repository: inputGitRepository, + title: 'My Awesome New Feature', + createdBy: inputIdentityRef, + creationDate: new Date('2020-09-12T06:10:23.9325232Z'), + sourceRefName: 'refs/heads/topic/super-awesome-feature', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + }; + + const inputBaseUrl = + 'https://host.com/myOrg/_git/super-feature-repo/pullrequest'; + + const outputPullRequest: PullRequest = { + pullRequestId: 7181, + repoName: 'super-feature-repo', + title: 'My Awesome New Feature', + uniqueName: 'DOMAINjdoe', + createdBy: 'Jane Doe', + creationDate: new Date('2020-09-12T06:10:23.9325232Z'), + sourceRefName: 'refs/heads/topic/super-awesome-feature', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'https://host.com/myOrg/_git/super-feature-repo/pullrequest/7181', + }; + + expect(mappedPullRequest(inputPullRequest, inputBaseUrl)).toEqual( + outputPullRequest, + ); }); }); }); diff --git a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts index 3da4dff11d..89e32aa2f3 100644 --- a/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts +++ b/plugins/azure-devops-backend/src/api/AzureDevOpsApi.ts @@ -16,12 +16,16 @@ import { Logger } from 'winston'; import { WebApi } from 'azure-devops-node-api'; -import { RepoBuild } from './types'; import { Build, BuildResult, BuildStatus, } from 'azure-devops-node-api/interfaces/BuildInterfaces'; +import { + GitPullRequest, + GitPullRequestSearchCriteria, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { PullRequest, PullRequestOptions, RepoBuild } from './types'; export class AzureDevOpsApi { constructor( @@ -88,14 +92,48 @@ export class AzureDevOpsApi { ); const repoBuilds: RepoBuild[] = buildList.map(build => { - return repoBuildFromBuild(build); + return mappedRepoBuild(build); }); return repoBuilds; } + + async getPullRequests( + projectName: string, + repoName: string, + options: PullRequestOptions, + ) { + if (this.logger) { + this.logger.debug( + `Calling Azure DevOps REST API, getting up to ${top} Pull Requests for Repository ${repoName} for Project ${projectName}`, + ); + } + + const gitRepository = await this.getGitRepository(projectName, repoName); + const client = await this.webApi.getGitApi(); + const searchCriteria: GitPullRequestSearchCriteria = { + status: options.status, + }; + const gitPullRequests = await client.getPullRequests( + gitRepository.id as string, + searchCriteria, + projectName, + undefined, + undefined, + options.top, + ); + const linkBaseUrl = `${this.webApi.serverUrl}/${encodeURIComponent( + projectName, + )}/_git/${encodeURIComponent(repoName)}/pullrequest`; + const pullRequests: PullRequest[] = gitPullRequests.map(gitPullRequest => { + return mappedPullRequest(gitPullRequest, linkBaseUrl); + }); + + return pullRequests; + } } -export function repoBuildFromBuild(build: Build) { +export function mappedRepoBuild(build: Build) { return { id: build.id, title: [build.definition?.name, build.buildNumber] @@ -108,3 +146,22 @@ export function repoBuildFromBuild(build: Build) { source: `${build.sourceBranch} (${build.sourceVersion?.substr(0, 8)})`, }; } + +export function mappedPullRequest( + pullRequest: GitPullRequest, + linkBaseUrl: string, +) { + return { + pullRequestId: pullRequest.pullRequestId, + repoName: pullRequest.repository?.name, + title: pullRequest.title, + uniqueName: pullRequest.createdBy?.uniqueName, + createdBy: pullRequest.createdBy?.displayName, + creationDate: pullRequest.creationDate, + sourceRefName: pullRequest.sourceRefName, + targetRefName: pullRequest.targetRefName, + status: pullRequest.status, + isDraft: pullRequest.isDraft, + link: `${linkBaseUrl}/${pullRequest.pullRequestId}`, + }; +} diff --git a/plugins/azure-devops-backend/src/api/index.ts b/plugins/azure-devops-backend/src/api/index.ts index 8faf37fe4e..893f0f4f2c 100644 --- a/plugins/azure-devops-backend/src/api/index.ts +++ b/plugins/azure-devops-backend/src/api/index.ts @@ -15,4 +15,4 @@ */ export { AzureDevOpsApi } from './AzureDevOpsApi'; -export type { RepoBuild } from './types'; +export type { RepoBuild, PullRequest } from './types'; diff --git a/plugins/azure-devops-backend/src/api/types.ts b/plugins/azure-devops-backend/src/api/types.ts index b3562f76c6..a53f501f26 100644 --- a/plugins/azure-devops-backend/src/api/types.ts +++ b/plugins/azure-devops-backend/src/api/types.ts @@ -18,6 +18,7 @@ import { BuildResult, BuildStatus, } from 'azure-devops-node-api/interfaces/BuildInterfaces'; +import { PullRequestStatus } from 'azure-devops-node-api/interfaces/GitInterfaces'; export type RepoBuild = { id?: number; @@ -28,3 +29,22 @@ export type RepoBuild = { queueTime?: Date; source: string; }; + +export type PullRequest = { + pullRequestId?: number; + repoName?: string; + title?: string; + uniqueName?: string; + createdBy?: string; + creationDate?: Date; + sourceRefName?: string; + targetRefName?: string; + status?: PullRequestStatus; + isDraft?: boolean; + link: string; +}; + +export type PullRequestOptions = { + top: number; + status: PullRequestStatus; +}; diff --git a/plugins/azure-devops-backend/src/index.ts b/plugins/azure-devops-backend/src/index.ts index a7004ec73e..ff4d3973bf 100644 --- a/plugins/azure-devops-backend/src/index.ts +++ b/plugins/azure-devops-backend/src/index.ts @@ -14,5 +14,5 @@ * limitations under the License. */ export { AzureDevOpsApi } from './api'; -export type { RepoBuild } from './api'; +export type { RepoBuild, PullRequest } from './api'; export * from './service/router'; diff --git a/plugins/azure-devops-backend/src/service/router.test.ts b/plugins/azure-devops-backend/src/service/router.test.ts index a66b86f418..4143291409 100644 --- a/plugins/azure-devops-backend/src/service/router.test.ts +++ b/plugins/azure-devops-backend/src/service/router.test.ts @@ -20,8 +20,11 @@ import express from 'express'; import request from 'supertest'; import { AzureDevOpsApi } from '../api'; import { createRouter } from './router'; -import { RepoBuild } from '../api/types'; -import { GitRepository } from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { PullRequest, RepoBuild } from '../api/types'; +import { + GitRepository, + PullRequestStatus, +} from 'azure-devops-node-api/interfaces/GitInterfaces'; import { Build, BuildResult, @@ -37,6 +40,7 @@ describe('createRouter', () => { getGitRepository: jest.fn(), getBuildList: jest.fn(), getRepoBuilds: jest.fn(), + getPullRequests: jest.fn(), } as any; const router = await createRouter({ azureDevOpsApi, @@ -193,4 +197,67 @@ describe('createRouter', () => { expect(response.body).toEqual(repoBuilds); }); }); + + describe('GET /pull-requests/:projectName/:repoName', () => { + it('fetches a list of pull requests', async () => { + const firstPullRequest: PullRequest = { + pullRequestId: 7181, + repoName: 'super-feature-repo', + title: 'My Awesome New Feature', + createdBy: 'Jane Doe', + creationDate: undefined, + sourceRefName: 'refs/heads/topic/super-awesome-feature', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'https://host.com/myOrg/_git/super-feature-repo/pullrequest/7181', + }; + + const secondPullRequest: PullRequest = { + pullRequestId: 7182, + repoName: 'super-feature-repo', + title: 'Refactoring My Awesome New Feature', + createdBy: 'Jane Doe', + creationDate: undefined, + sourceRefName: 'refs/heads/topic/refactor-super-awesome-feature', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'https://host.com/myOrg/_git/super-feature-repo/pullrequest/7182', + }; + + const thirdPullRequest: PullRequest = { + pullRequestId: 7183, + repoName: 'super-feature-repo', + title: 'Bug Fix for My Awesome New Feature', + createdBy: 'Jane Doe', + creationDate: undefined, + sourceRefName: 'refs/heads/topic/fix-super-awesome-feature', + targetRefName: 'refs/heads/main', + status: PullRequestStatus.Active, + isDraft: false, + link: 'https://host.com/myOrg/_git/super-feature-repo/pullrequest/7183', + }; + + const pullRequests: PullRequest[] = [ + firstPullRequest, + secondPullRequest, + thirdPullRequest, + ]; + + azureDevOpsApi.getPullRequests.mockResolvedValueOnce(pullRequests); + + const response = await request(app) + .get('/pull-requests/myProject/myRepo') + .query({ top: '50', status: 1 }); + + expect(azureDevOpsApi.getPullRequests).toHaveBeenCalledWith( + 'myProject', + 'myRepo', + { status: 1, top: 50 }, + ); + expect(response.status).toEqual(200); + expect(response.body).toEqual(pullRequests); + }); + }); }); diff --git a/plugins/azure-devops-backend/src/service/router.ts b/plugins/azure-devops-backend/src/service/router.ts index 1fc86128e6..0929d5cde9 100644 --- a/plugins/azure-devops-backend/src/service/router.ts +++ b/plugins/azure-devops-backend/src/service/router.ts @@ -21,6 +21,8 @@ import { Logger } from 'winston'; import { Config } from '@backstage/config'; import { getPersonalAccessTokenHandler, WebApi } from 'azure-devops-node-api'; import { AzureDevOpsApi } from '../api'; +import { PullRequestStatus } from 'azure-devops-node-api/interfaces/GitInterfaces'; +import { PullRequestOptions } from '../api/types'; const DEFAULT_TOP: number = 10; @@ -84,6 +86,24 @@ export async function createRouter( res.status(200).json(gitRepository); }); + router.get('/pull-requests/:projectName/:repoName', async (req, res) => { + const { projectName, repoName } = req.params; + const top = req.query.top ? Number(req.query.top) : DEFAULT_TOP; + const status = req.query.status + ? Number(req.query.status) + : PullRequestStatus.Active; + const pullRequestOptions: PullRequestOptions = { + top: top, + status: status, + }; + const gitPullRequest = await azureDevOpsApi.getPullRequests( + projectName, + repoName, + pullRequestOptions, + ); + res.status(200).json(gitPullRequest); + }); + router.use(errorHandler()); return router; } diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts similarity index 99% rename from plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts rename to plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts index 5f509747f3..00b3de2fc7 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.test.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.test.ts @@ -28,7 +28,7 @@ import { DbRefreshStateRow, DbRelationsRow, } from './tables'; -import { createRandomRefreshInterval } from '../refresh'; +import { createRandomRefreshInterval } from '../processing/refresh'; import { timestampToDateTime } from './conversion'; import { generateStableHash } from './util'; diff --git a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts similarity index 99% rename from plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts rename to plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts index b47154a46f..9785ac3935 100644 --- a/plugins/catalog-backend/src/next/database/DefaultProcessingDatabase.ts +++ b/plugins/catalog-backend/src/database/DefaultProcessingDatabase.ts @@ -33,7 +33,7 @@ import { UpdateEntityCacheOptions, } from './types'; import { DeferredEntity } from '../processing/types'; -import { RefreshIntervalFunction } from '../refresh'; +import { RefreshIntervalFunction } from '../processing/refresh'; import { rethrowError, timestampToDateTime } from './conversion'; import { initDatabaseMetrics } from './metrics'; import { diff --git a/plugins/catalog-backend/src/next/database/conversion.test.ts b/plugins/catalog-backend/src/database/conversion.test.ts similarity index 100% rename from plugins/catalog-backend/src/next/database/conversion.test.ts rename to plugins/catalog-backend/src/database/conversion.test.ts diff --git a/plugins/catalog-backend/src/next/database/conversion.ts b/plugins/catalog-backend/src/database/conversion.ts similarity index 100% rename from plugins/catalog-backend/src/next/database/conversion.ts rename to plugins/catalog-backend/src/database/conversion.ts diff --git a/plugins/catalog-backend/src/next/database/metrics.ts b/plugins/catalog-backend/src/database/metrics.ts similarity index 97% rename from plugins/catalog-backend/src/next/database/metrics.ts rename to plugins/catalog-backend/src/database/metrics.ts index 4ad319ed10..b6c4e248dc 100644 --- a/plugins/catalog-backend/src/next/database/metrics.ts +++ b/plugins/catalog-backend/src/database/metrics.ts @@ -15,7 +15,7 @@ */ import { Knex } from 'knex'; -import { createGaugeMetric } from '../metrics'; +import { createGaugeMetric } from '../util/metrics'; import { DbRefreshStateRow, DbRelationsRow, DbLocationsRow } from './tables'; export function initDatabaseMetrics(knex: Knex) { diff --git a/plugins/catalog-backend/src/next/database/migrations.ts b/plugins/catalog-backend/src/database/migrations.ts similarity index 100% rename from plugins/catalog-backend/src/next/database/migrations.ts rename to plugins/catalog-backend/src/database/migrations.ts diff --git a/plugins/catalog-backend/src/next/database/tables.ts b/plugins/catalog-backend/src/database/tables.ts similarity index 100% rename from plugins/catalog-backend/src/next/database/tables.ts rename to plugins/catalog-backend/src/database/tables.ts diff --git a/plugins/catalog-backend/src/next/database/types.ts b/plugins/catalog-backend/src/database/types.ts similarity index 100% rename from plugins/catalog-backend/src/next/database/types.ts rename to plugins/catalog-backend/src/database/types.ts diff --git a/plugins/catalog-backend/src/next/database/util.ts b/plugins/catalog-backend/src/database/util.ts similarity index 100% rename from plugins/catalog-backend/src/next/database/util.ts rename to plugins/catalog-backend/src/database/util.ts diff --git a/plugins/catalog-backend/src/index.ts b/plugins/catalog-backend/src/index.ts index 4d84330f27..7ad888bee4 100644 --- a/plugins/catalog-backend/src/index.ts +++ b/plugins/catalog-backend/src/index.ts @@ -25,4 +25,6 @@ export * from './ingestion'; export * from './legacy'; export * from './search'; export * from './util'; -export * from './next'; +export * from './processing'; +export * from './providers'; +export * from './service'; diff --git a/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.test.ts index 435ad368c7..064a2ad724 100644 --- a/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/AwsS3DiscoveryProcessor.test.ts @@ -37,13 +37,8 @@ AWSMock.mock( Buffer.from( require('fs').readFileSync( path.resolve( - 'src', - 'ingestion', - 'processors', - '__fixtures__', - 'fileReaderProcessor', - 'awsS3', - 'awsS3-mock-object.txt', + __dirname, + '__fixtures__/fileReaderProcessor/awsS3/awsS3-mock-object.txt', ), ), ), diff --git a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts index 41c7e4f732..8a5f202e5e 100644 --- a/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts +++ b/plugins/catalog-backend/src/ingestion/processors/FileReaderProcessor.test.ts @@ -23,13 +23,7 @@ import { import path from 'path'; describe('FileReaderProcessor', () => { - const fixturesRoot = path.join( - 'src', - 'ingestion', - 'processors', - '__fixtures__', - 'fileReaderProcessor', - ); + const fixturesRoot = path.join(__dirname, '__fixtures__/fileReaderProcessor'); it('should load from file', async () => { const processor = new FileReaderProcessor(); diff --git a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts index 1b366130ed..926aa67635 100644 --- a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts +++ b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.test.ts @@ -23,7 +23,7 @@ import { DatabaseManager } from '../database'; import { CatalogProcessorParser } from '../../ingestion'; import * as result from '../../ingestion/processors/results'; import { CatalogBuilder } from './CatalogBuilder'; -import { CatalogEnvironment } from '../../next'; +import { CatalogEnvironment } from '../../service'; const dummyEntity = { apiVersion: 'backstage.io/v1alpha1', diff --git a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts index 1a151b77d6..b8e45c7cf3 100644 --- a/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts +++ b/plugins/catalog-backend/src/legacy/service/CatalogBuilder.ts @@ -64,7 +64,7 @@ import { } from '../../ingestion/processors/PlaceholderProcessor'; import { defaultEntityDataParser } from '../../ingestion/processors/util/parse'; import { LocationAnalyzer } from '../../ingestion/types'; -import { CatalogEnvironment, NextCatalogBuilder } from '../../next'; +import { CatalogEnvironment, NextCatalogBuilder } from '../../service'; /** * A builder that helps wire up all of the component parts of the catalog. diff --git a/plugins/catalog-backend/src/legacy/service/router.test.ts b/plugins/catalog-backend/src/legacy/service/router.test.ts index d15d3799b5..edc7d852ac 100644 --- a/plugins/catalog-backend/src/legacy/service/router.test.ts +++ b/plugins/catalog-backend/src/legacy/service/router.test.ts @@ -25,7 +25,7 @@ import { LocationResponse, LocationsCatalog } from '../catalog/types'; import { HigherOrderOperation } from '../ingestion/types'; import { createRouter } from './router'; import { basicEntityFilter } from '../../service/request'; -import { RefreshService } from '../../next'; +import { RefreshService } from '../../service'; describe('createRouter readonly disabled', () => { let entitiesCatalog: jest.Mocked>; diff --git a/plugins/catalog-backend/src/legacy/service/router.ts b/plugins/catalog-backend/src/legacy/service/router.ts index 4dfa9e49f9..e7d097a9c7 100644 --- a/plugins/catalog-backend/src/legacy/service/router.ts +++ b/plugins/catalog-backend/src/legacy/service/router.ts @@ -34,7 +34,7 @@ import { RefreshService, LocationService, RefreshOptions, -} from '../../next/types'; +} from '../../service/types'; import { basicEntityFilter, parseEntityFilterParams, diff --git a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts b/plugins/catalog-backend/src/next/Context/ContextWithValue.ts deleted file mode 100644 index cc88c03679..0000000000 --- a/plugins/catalog-backend/src/next/Context/ContextWithValue.ts +++ /dev/null @@ -1,39 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { Context, ContextKey } from './types'; - -/** - * A Context implementation that holds a single value, optionally extending an existing context. - */ -export class ContextWithValue implements Context { - static create(parent: Context, key: ContextKey, value: unknown) { - return new ContextWithValue(parent, key, value); - } - - private constructor( - private readonly parent: Context, - private readonly key: ContextKey, - private readonly value: unknown, - ) {} - - getContextValue(key: ContextKey): T { - if (this.key === key) { - return this.value as T; - } - return this.parent.getContextValue(key); - } -} diff --git a/plugins/catalog-backend/src/next/Context/TransactionValue.test.ts b/plugins/catalog-backend/src/next/Context/TransactionValue.test.ts deleted file mode 100644 index 20165eff2f..0000000000 --- a/plugins/catalog-backend/src/next/Context/TransactionValue.test.ts +++ /dev/null @@ -1,37 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { TransactionValue } from './TransactionValue'; -import { Knex } from 'knex'; -import { BackgroundContext } from './BackgroundContext'; - -describe('TransactionValue Context', () => { - it('should be able to store tx values and retrieve them from a context', () => { - const tx = {} as Knex.Transaction; - const ctx = new BackgroundContext(); - - const nextCtx = TransactionValue.in(ctx, tx); - - expect(TransactionValue.from(nextCtx)).toBe(tx); - }); - - it('should throw when there is no tx value in the context', () => { - const ctx = new BackgroundContext(); - - expect(() => TransactionValue.from(ctx)).toThrow( - /No transaction available in context/, - ); - }); -}); diff --git a/plugins/catalog-backend/src/next/Context/TransactionValue.ts b/plugins/catalog-backend/src/next/Context/TransactionValue.ts deleted file mode 100644 index af069c6d8e..0000000000 --- a/plugins/catalog-backend/src/next/Context/TransactionValue.ts +++ /dev/null @@ -1,40 +0,0 @@ -/* - * Copyright 2021 The Backstage Authors - * - * 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 { Context, ContextKey } from './types'; -import { Knex } from 'knex'; -import { ContextWithValue } from './ContextWithValue'; - -const transactionContextKey = new ContextKey( - undefined, -); - -/** - * TransactionValue handles the wrapping of a knex transaction in a Context. - */ -export class TransactionValue { - static in(parent: Context, tx: Knex.Transaction) { - return ContextWithValue.create(parent, transactionContextKey, tx); - } - - static from(context: Context): Knex.Transaction { - const transaction = context.getContextValue(transactionContextKey); - if (!transaction) { - throw new Error(`No transaction available in context`); - } - return transaction; - } -} diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.test.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.test.ts similarity index 97% rename from plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.test.ts rename to plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.test.ts index 430d7f251f..044c3e7c4b 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.test.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.test.ts @@ -18,10 +18,10 @@ import { getVoidLogger } from '@backstage/backend-common'; import { Hash } from 'crypto'; import { DateTime } from 'luxon'; import waitForExpect from 'wait-for-expect'; -import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; +import { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase'; import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; -import { CatalogProcessingOrchestrator } from './processing/types'; -import { Stitcher } from './stitching/Stitcher'; +import { CatalogProcessingOrchestrator } from './types'; +import { Stitcher } from '../stitching/Stitcher'; describe('DefaultCatalogProcessingEngine', () => { const db = { diff --git a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts similarity index 97% rename from plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts rename to plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts index 346a912009..d0faff25d5 100644 --- a/plugins/catalog-backend/src/next/DefaultCatalogProcessingEngine.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingEngine.ts @@ -23,20 +23,20 @@ import { serializeError } from '@backstage/errors'; import { Hash } from 'crypto'; import stableStringify from 'fast-json-stable-stringify'; import { Logger } from 'winston'; -import { ProcessingDatabase, RefreshStateItem } from './database/types'; -import { createCounterMetric, createSummaryMetric } from './metrics'; -import { - CatalogProcessingOrchestrator, - EntityProcessingResult, -} from './processing/types'; -import { Stitcher } from './stitching/Stitcher'; -import { startTaskPipeline } from './TaskPipeline'; +import { ProcessingDatabase, RefreshStateItem } from '../database/types'; +import { createCounterMetric, createSummaryMetric } from '../util/metrics'; import { CatalogProcessingEngine, + CatalogProcessingOrchestrator, + EntityProcessingResult, +} from '../processing/types'; +import { Stitcher } from '../stitching/Stitcher'; +import { startTaskPipeline } from './TaskPipeline'; +import { EntityProvider, EntityProviderConnection, EntityProviderMutation, -} from './types'; +} from '../providers/types'; const CACHE_TTL = 5; diff --git a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.test.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts similarity index 97% rename from plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.test.ts rename to plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts index 098f3ac14d..5ae4d58ec7 100644 --- a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.test.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.test.ts @@ -30,10 +30,10 @@ import { CatalogProcessorEmit, CatalogProcessorParser, results, -} from '../../ingestion'; -import { CatalogRulesEnforcer } from '../../ingestion/CatalogRules'; +} from '../ingestion'; +import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; import { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; -import { defaultEntityDataParser } from '../../ingestion/processors/util/parse'; +import { defaultEntityDataParser } from '../ingestion/processors/util/parse'; import { ConfigReader } from '@backstage/config'; class FooBarProcessor implements CatalogProcessor { diff --git a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts similarity index 98% rename from plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts rename to plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts index 7a3977bcca..e973dcbf0c 100644 --- a/plugins/catalog-backend/src/next/processing/DefaultCatalogProcessingOrchestrator.ts +++ b/plugins/catalog-backend/src/processing/DefaultCatalogProcessingOrchestrator.ts @@ -31,8 +31,8 @@ import { Logger } from 'winston'; import { CatalogProcessor, CatalogProcessorParser, -} from '../../ingestion/processors'; -import * as results from '../../ingestion/processors/results'; +} from '../ingestion/processors'; +import * as results from '../ingestion/processors/results'; import { CatalogProcessingOrchestrator, EntityProcessingRequest, @@ -48,7 +48,7 @@ import { validateEntityEnvelope, isObject, } from './util'; -import { CatalogRulesEnforcer } from '../../ingestion/CatalogRules'; +import { CatalogRulesEnforcer } from '../ingestion/CatalogRules'; import { ProcessorCacheManager } from './ProcessorCacheManager'; type Context = { diff --git a/plugins/catalog-backend/src/next/processing/ProcessorCacheManager.test.ts b/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts similarity index 98% rename from plugins/catalog-backend/src/next/processing/ProcessorCacheManager.test.ts rename to plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts index 44c96da1ca..e7f9fb313b 100644 --- a/plugins/catalog-backend/src/next/processing/ProcessorCacheManager.test.ts +++ b/plugins/catalog-backend/src/processing/ProcessorCacheManager.test.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { CatalogProcessor } from '../../ingestion/processors'; +import { CatalogProcessor } from '../ingestion/processors'; import { ProcessorCacheManager } from './ProcessorCacheManager'; class MyProcessor implements CatalogProcessor { diff --git a/plugins/catalog-backend/src/next/processing/ProcessorCacheManager.ts b/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts similarity index 96% rename from plugins/catalog-backend/src/next/processing/ProcessorCacheManager.ts rename to plugins/catalog-backend/src/processing/ProcessorCacheManager.ts index 16945b7cc9..378974e33e 100644 --- a/plugins/catalog-backend/src/next/processing/ProcessorCacheManager.ts +++ b/plugins/catalog-backend/src/processing/ProcessorCacheManager.ts @@ -15,8 +15,8 @@ */ import { JsonObject, JsonValue } from '@backstage/config'; -import { CatalogProcessor } from '../../ingestion/processors'; -import { CatalogProcessorCache } from '../../ingestion/processors/types'; +import { CatalogProcessor } from '../ingestion/processors'; +import { CatalogProcessorCache } from '../ingestion/processors/types'; import { isObject } from './util'; class SingleProcessorSubCache implements CatalogProcessorCache { diff --git a/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts similarity index 96% rename from plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts rename to plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts index 507def964a..dfaa25418b 100644 --- a/plugins/catalog-backend/src/next/processing/ProcessorOutputCollector.ts +++ b/plugins/catalog-backend/src/processing/ProcessorOutputCollector.ts @@ -22,8 +22,8 @@ import { stringifyLocationReference, } from '@backstage/catalog-model'; import { Logger } from 'winston'; -import { CatalogProcessorResult } from '../../ingestion'; -import { locationSpecToLocationEntity } from '../util'; +import { CatalogProcessorResult } from '../ingestion'; +import { locationSpecToLocationEntity } from '../util/conversion'; import { DeferredEntity } from './types'; import { getEntityLocationRef, diff --git a/plugins/catalog-backend/src/next/TaskPipeline.test.ts b/plugins/catalog-backend/src/processing/TaskPipeline.test.ts similarity index 100% rename from plugins/catalog-backend/src/next/TaskPipeline.test.ts rename to plugins/catalog-backend/src/processing/TaskPipeline.test.ts diff --git a/plugins/catalog-backend/src/next/TaskPipeline.ts b/plugins/catalog-backend/src/processing/TaskPipeline.ts similarity index 100% rename from plugins/catalog-backend/src/next/TaskPipeline.ts rename to plugins/catalog-backend/src/processing/TaskPipeline.ts diff --git a/plugins/catalog-backend/src/next/processing/index.ts b/plugins/catalog-backend/src/processing/index.ts similarity index 85% rename from plugins/catalog-backend/src/next/processing/index.ts rename to plugins/catalog-backend/src/processing/index.ts index 9e03f18f28..dc8b07eceb 100644 --- a/plugins/catalog-backend/src/next/processing/index.ts +++ b/plugins/catalog-backend/src/processing/index.ts @@ -16,8 +16,12 @@ export type { CatalogProcessingOrchestrator, + CatalogProcessingEngine, EntityProcessingRequest, EntityProcessingResult, DeferredEntity, } from './types'; export { DefaultCatalogProcessingOrchestrator } from './DefaultCatalogProcessingOrchestrator'; + +export { createRandomRefreshInterval } from './refresh'; +export type { RefreshIntervalFunction } from './refresh'; diff --git a/plugins/catalog-backend/src/next/refresh.ts b/plugins/catalog-backend/src/processing/refresh.ts similarity index 100% rename from plugins/catalog-backend/src/next/refresh.ts rename to plugins/catalog-backend/src/processing/refresh.ts diff --git a/plugins/catalog-backend/src/next/processing/types.ts b/plugins/catalog-backend/src/processing/types.ts similarity index 93% rename from plugins/catalog-backend/src/next/processing/types.ts rename to plugins/catalog-backend/src/processing/types.ts index 8b533714ce..4b16ccef32 100644 --- a/plugins/catalog-backend/src/next/processing/types.ts +++ b/plugins/catalog-backend/src/processing/types.ts @@ -44,3 +44,8 @@ export type DeferredEntity = { entity: Entity; locationKey?: string; }; + +export interface CatalogProcessingEngine { + start(): Promise; + stop(): Promise; +} diff --git a/plugins/catalog-backend/src/next/processing/util.ts b/plugins/catalog-backend/src/processing/util.ts similarity index 100% rename from plugins/catalog-backend/src/next/processing/util.ts rename to plugins/catalog-backend/src/processing/util.ts diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts b/plugins/catalog-backend/src/providers/ConfigLocationEntityProvider.test.ts similarity index 94% rename from plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts rename to plugins/catalog-backend/src/providers/ConfigLocationEntityProvider.test.ts index ef3e47eb8b..0663ad8d04 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.test.ts +++ b/plugins/catalog-backend/src/providers/ConfigLocationEntityProvider.test.ts @@ -14,7 +14,6 @@ * limitations under the License. */ -import { resolvePackagePath } from '@backstage/backend-common'; import { ConfigReader } from '@backstage/config'; import path from 'path'; import { ConfigLocationEntityProvider } from './ConfigLocationEntityProvider'; @@ -44,10 +43,7 @@ describe('ConfigLocationEntityProvider', () => { { entity: expect.objectContaining({ spec: { - target: path.join( - resolvePackagePath('@backstage/plugin-catalog-backend'), - './lols.yaml', - ), + target: path.join(process.cwd(), 'lols.yaml'), type: 'file', }, }), diff --git a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts b/plugins/catalog-backend/src/providers/ConfigLocationEntityProvider.ts similarity index 94% rename from plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts rename to plugins/catalog-backend/src/providers/ConfigLocationEntityProvider.ts index 5deca09944..389cd8d9ff 100644 --- a/plugins/catalog-backend/src/next/ConfigLocationEntityProvider.ts +++ b/plugins/catalog-backend/src/providers/ConfigLocationEntityProvider.ts @@ -16,9 +16,9 @@ import { Config } from '@backstage/config'; import path from 'path'; -import { getEntityLocationRef } from './processing/util'; +import { getEntityLocationRef } from '../processing/util'; import { EntityProvider, EntityProviderConnection } from './types'; -import { locationSpecToLocationEntity } from './util'; +import { locationSpecToLocationEntity } from '../util/conversion'; export class ConfigLocationEntityProvider implements EntityProvider { constructor(private readonly config: Config) {} diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts b/plugins/catalog-backend/src/providers/DefaultLocationStore.test.ts similarity index 98% rename from plugins/catalog-backend/src/next/DefaultLocationStore.test.ts rename to plugins/catalog-backend/src/providers/DefaultLocationStore.test.ts index f3cefeb14f..b9d129de5f 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.test.ts +++ b/plugins/catalog-backend/src/providers/DefaultLocationStore.test.ts @@ -15,7 +15,7 @@ */ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { v4 as uuid } from 'uuid'; -import { applyDatabaseMigrations } from './database/migrations'; +import { applyDatabaseMigrations } from '../database/migrations'; import { DefaultLocationStore } from './DefaultLocationStore'; describe('DefaultLocationStore', () => { diff --git a/plugins/catalog-backend/src/next/DefaultLocationStore.ts b/plugins/catalog-backend/src/providers/DefaultLocationStore.ts similarity index 93% rename from plugins/catalog-backend/src/next/DefaultLocationStore.ts rename to plugins/catalog-backend/src/providers/DefaultLocationStore.ts index c9ffe9a682..9214cd0bc1 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationStore.ts +++ b/plugins/catalog-backend/src/providers/DefaultLocationStore.ts @@ -18,14 +18,11 @@ import { Location, LocationSpec } from '@backstage/catalog-model'; import { ConflictError, NotFoundError } from '@backstage/errors'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; -import { DbLocationsRow } from './database/tables'; -import { getEntityLocationRef } from './processing/util'; -import { - EntityProvider, - EntityProviderConnection, - LocationStore, -} from './types'; -import { locationSpecToLocationEntity } from './util'; +import { DbLocationsRow } from '../database/tables'; +import { getEntityLocationRef } from '../processing/util'; +import { EntityProvider, EntityProviderConnection } from './types'; +import { locationSpecToLocationEntity } from '../util/conversion'; +import { LocationStore } from '../service'; export class DefaultLocationStore implements LocationStore, EntityProvider { private _connection: EntityProviderConnection | undefined; diff --git a/plugins/catalog-backend/src/next/Context/types.ts b/plugins/catalog-backend/src/providers/index.ts similarity index 80% rename from plugins/catalog-backend/src/next/Context/types.ts rename to plugins/catalog-backend/src/providers/index.ts index 062bc884e9..3b4a1c4b7e 100644 --- a/plugins/catalog-backend/src/next/Context/types.ts +++ b/plugins/catalog-backend/src/providers/index.ts @@ -14,10 +14,8 @@ * limitations under the License. */ -export class ContextKey { - constructor(readonly defaultValue: T) {} -} - -export interface Context { - getContextValue(key: ContextKey): T; -} +export type { + EntityProvider, + EntityProviderConnection, + EntityProviderMutation, +} from './types'; diff --git a/plugins/catalog-backend/src/next/Context/BackgroundContext.ts b/plugins/catalog-backend/src/providers/types.ts similarity index 57% rename from plugins/catalog-backend/src/next/Context/BackgroundContext.ts rename to plugins/catalog-backend/src/providers/types.ts index c41fa8e3c5..90c5f13215 100644 --- a/plugins/catalog-backend/src/next/Context/BackgroundContext.ts +++ b/plugins/catalog-backend/src/providers/types.ts @@ -14,13 +14,17 @@ * limitations under the License. */ -import { Context, ContextKey } from './types'; +import { DeferredEntity } from '../processing'; -/** - * A base Context implementation that does not hold any value. - */ -export class BackgroundContext implements Context { - getContextValue(key: ContextKey): T { - return key.defaultValue; - } +export type EntityProviderMutation = + | { type: 'full'; entities: DeferredEntity[] } + | { type: 'delta'; added: DeferredEntity[]; removed: DeferredEntity[] }; + +export interface EntityProviderConnection { + applyMutation(mutation: EntityProviderMutation): Promise; +} + +export interface EntityProvider { + getProviderName(): string; + connect(connection: EntityProviderConnection): Promise; } diff --git a/plugins/catalog-backend/src/next/DefaultLocationService.test.ts b/plugins/catalog-backend/src/service/DefaultLocationService.test.ts similarity index 98% rename from plugins/catalog-backend/src/next/DefaultLocationService.test.ts rename to plugins/catalog-backend/src/service/DefaultLocationService.test.ts index 78dd9c1009..a089989d20 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationService.test.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.test.ts @@ -15,7 +15,7 @@ */ import { DefaultLocationService } from './DefaultLocationService'; -import { CatalogProcessingOrchestrator } from './processing/types'; +import { CatalogProcessingOrchestrator } from '../processing/types'; import { LocationStore } from './types'; describe('DefaultLocationServiceTest', () => { diff --git a/plugins/catalog-backend/src/next/DefaultLocationService.ts b/plugins/catalog-backend/src/service/DefaultLocationService.ts similarity index 97% rename from plugins/catalog-backend/src/next/DefaultLocationService.ts rename to plugins/catalog-backend/src/service/DefaultLocationService.ts index 678ce9791c..2166341935 100644 --- a/plugins/catalog-backend/src/next/DefaultLocationService.ts +++ b/plugins/catalog-backend/src/service/DefaultLocationService.ts @@ -23,9 +23,9 @@ import { import { CatalogProcessingOrchestrator, DeferredEntity, -} from './processing/types'; +} from '../processing/types'; import { LocationService, LocationStore } from './types'; -import { locationSpecToMetadataName } from './util'; +import { locationSpecToMetadataName } from '../util/conversion'; export class DefaultLocationService implements LocationService { constructor( diff --git a/plugins/catalog-backend/src/next/DefaultRefreshService.test.ts b/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts similarity index 95% rename from plugins/catalog-backend/src/next/DefaultRefreshService.test.ts rename to plugins/catalog-backend/src/service/DefaultRefreshService.test.ts index 7b6a181375..0ea475a528 100644 --- a/plugins/catalog-backend/src/next/DefaultRefreshService.test.ts +++ b/plugins/catalog-backend/src/service/DefaultRefreshService.test.ts @@ -19,16 +19,16 @@ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { createHash } from 'crypto'; import { Knex } from 'knex'; import { Logger } from 'winston'; -import { applyDatabaseMigrations } from './database/migrations'; -import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; +import { applyDatabaseMigrations } from '../database/migrations'; +import { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase'; import { DbRefreshStateReferencesRow, DbRefreshStateRow, -} from './database/tables'; -import { ProcessingDatabase } from './database/types'; -import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; -import { EntityProcessingRequest } from './processing/types'; -import { Stitcher } from './stitching/Stitcher'; +} from '../database/tables'; +import { ProcessingDatabase } from '../database/types'; +import { DefaultCatalogProcessingEngine } from '../processing/DefaultCatalogProcessingEngine'; +import { EntityProcessingRequest } from '../processing/types'; +import { Stitcher } from '../stitching/Stitcher'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { v4 as uuid } from 'uuid'; import { DefaultRefreshService } from './DefaultRefreshService'; diff --git a/plugins/catalog-backend/src/next/DefaultRefreshService.ts b/plugins/catalog-backend/src/service/DefaultRefreshService.ts similarity index 95% rename from plugins/catalog-backend/src/next/DefaultRefreshService.ts rename to plugins/catalog-backend/src/service/DefaultRefreshService.ts index cfc7fa220b..3b982a0e46 100644 --- a/plugins/catalog-backend/src/next/DefaultRefreshService.ts +++ b/plugins/catalog-backend/src/service/DefaultRefreshService.ts @@ -14,7 +14,7 @@ * limitations under the License. */ -import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; +import { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase'; import { RefreshOptions, RefreshService } from './types'; export class DefaultRefreshService implements RefreshService { diff --git a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts similarity index 95% rename from plugins/catalog-backend/src/next/NextCatalogBuilder.ts rename to plugins/catalog-backend/src/service/NextCatalogBuilder.ts index 8ca93d4bd7..60a1668f37 100644 --- a/plugins/catalog-backend/src/next/NextCatalogBuilder.ts +++ b/plugins/catalog-backend/src/service/NextCatalogBuilder.ts @@ -59,29 +59,27 @@ import { } from '../ingestion/processors/PlaceholderProcessor'; import { defaultEntityDataParser } from '../ingestion/processors/util/parse'; import { LocationAnalyzer } from '../ingestion/types'; -import { - CatalogProcessingEngine, - EntityProvider, - LocationService, -} from '../next/types'; -import { ConfigLocationEntityProvider } from './ConfigLocationEntityProvider'; -import { DefaultProcessingDatabase } from './database/DefaultProcessingDatabase'; -import { applyDatabaseMigrations } from './database/migrations'; -import { DefaultCatalogProcessingEngine } from './DefaultCatalogProcessingEngine'; +import { EntityProvider } from '../providers/types'; +import { CatalogProcessingEngine } from '../processing/types'; +import { ConfigLocationEntityProvider } from '../providers/ConfigLocationEntityProvider'; +import { DefaultProcessingDatabase } from '../database/DefaultProcessingDatabase'; +import { applyDatabaseMigrations } from '../database/migrations'; +import { DefaultCatalogProcessingEngine } from '../processing/DefaultCatalogProcessingEngine'; import { DefaultLocationService } from './DefaultLocationService'; -import { DefaultLocationStore } from './DefaultLocationStore'; +import { DefaultLocationStore } from '../providers/DefaultLocationStore'; import { NextEntitiesCatalog } from './NextEntitiesCatalog'; -import { DefaultCatalogProcessingOrchestrator } from './processing/DefaultCatalogProcessingOrchestrator'; -import { Stitcher } from './stitching/Stitcher'; +import { DefaultCatalogProcessingOrchestrator } from '../processing/DefaultCatalogProcessingOrchestrator'; +import { Stitcher } from '../stitching/Stitcher'; import { createRandomRefreshInterval, RefreshIntervalFunction, -} from './refresh'; +} from '../processing/refresh'; import { createNextRouter } from './NextRouter'; import { DefaultRefreshService } from './DefaultRefreshService'; import { DefaultCatalogRulesEnforcer } from '../ingestion/CatalogRules'; import { Config } from '@backstage/config'; import { Logger } from 'winston'; +import { LocationService } from './types'; export type CatalogEnvironment = { logger: Logger; diff --git a/plugins/catalog-backend/src/next/NextEntitiesCatalog.test.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts similarity index 98% rename from plugins/catalog-backend/src/next/NextEntitiesCatalog.test.ts rename to plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts index 47e92445e9..082aa47df5 100644 --- a/plugins/catalog-backend/src/next/NextEntitiesCatalog.test.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.test.ts @@ -18,12 +18,12 @@ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { Knex } from 'knex'; import { v4 as uuid } from 'uuid'; -import { applyDatabaseMigrations } from './database/migrations'; +import { applyDatabaseMigrations } from '../database/migrations'; import { DbFinalEntitiesRow, DbRefreshStateReferencesRow, DbRefreshStateRow, -} from './database/tables'; +} from '../database/tables'; import { NextEntitiesCatalog } from './NextEntitiesCatalog'; describe('NextEntitiesCatalog', () => { diff --git a/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts similarity index 99% rename from plugins/catalog-backend/src/next/NextEntitiesCatalog.ts rename to plugins/catalog-backend/src/service/NextEntitiesCatalog.ts index 4fde078a8b..0891be045d 100644 --- a/plugins/catalog-backend/src/next/NextEntitiesCatalog.ts +++ b/plugins/catalog-backend/src/service/NextEntitiesCatalog.ts @@ -30,7 +30,7 @@ import { DbRefreshStateRow, DbSearchRow, DbPageInfo, -} from './database/tables'; +} from '../database/tables'; function parsePagination(input?: EntityPagination): { limit?: number; diff --git a/plugins/catalog-backend/src/next/NextRouter.test.ts b/plugins/catalog-backend/src/service/NextRouter.test.ts similarity index 99% rename from plugins/catalog-backend/src/next/NextRouter.test.ts rename to plugins/catalog-backend/src/service/NextRouter.test.ts index 489e7efdb5..57911c74fb 100644 --- a/plugins/catalog-backend/src/next/NextRouter.test.ts +++ b/plugins/catalog-backend/src/service/NextRouter.test.ts @@ -22,7 +22,7 @@ import express from 'express'; import request from 'supertest'; import { EntitiesCatalog } from '../catalog'; import { LocationService, RefreshService } from './types'; -import { basicEntityFilter } from '../service/request'; +import { basicEntityFilter } from './request'; import { createNextRouter } from './NextRouter'; describe('createNextRouter readonly disabled', () => { diff --git a/plugins/catalog-backend/src/next/NextRouter.ts b/plugins/catalog-backend/src/service/NextRouter.ts similarity index 100% rename from plugins/catalog-backend/src/next/NextRouter.ts rename to plugins/catalog-backend/src/service/NextRouter.ts diff --git a/plugins/catalog-backend/src/next/index.ts b/plugins/catalog-backend/src/service/index.ts similarity index 77% rename from plugins/catalog-backend/src/next/index.ts rename to plugins/catalog-backend/src/service/index.ts index bbc68651ea..5345f79628 100644 --- a/plugins/catalog-backend/src/next/index.ts +++ b/plugins/catalog-backend/src/service/index.ts @@ -14,21 +14,13 @@ * limitations under the License. */ -export type { CatalogEnvironment } from './NextCatalogBuilder'; -export { NextCatalogBuilder } from './NextCatalogBuilder'; +export type { + LocationService, + RefreshService, + RefreshOptions, + LocationStore, +} from './types'; export { createNextRouter } from './NextRouter'; export type { NextRouterOptions } from './NextRouter'; -export * from './processing'; -export { createRandomRefreshInterval } from './refresh'; -export type { RefreshIntervalFunction } from './refresh'; -export * from './stitching'; -export type { - EntityProvider, - EntityProviderConnection, - EntityProviderMutation, - CatalogProcessingEngine, - LocationService, - LocationStore, - RefreshOptions, - RefreshService, -} from './types'; +export type { CatalogEnvironment } from './NextCatalogBuilder'; +export { NextCatalogBuilder } from './NextCatalogBuilder'; diff --git a/plugins/catalog-backend/src/next/types.ts b/plugins/catalog-backend/src/service/types.ts similarity index 72% rename from plugins/catalog-backend/src/next/types.ts rename to plugins/catalog-backend/src/service/types.ts index 4131b5835b..05d3d00f4d 100644 --- a/plugins/catalog-backend/src/next/types.ts +++ b/plugins/catalog-backend/src/service/types.ts @@ -14,8 +14,7 @@ * limitations under the License. */ -import { Entity, Location, LocationSpec } from '@backstage/catalog-model'; -import { DeferredEntity } from './processing/types'; +import { Entity, LocationSpec, Location } from '@backstage/catalog-model'; export interface LocationService { createLocation( @@ -27,18 +26,6 @@ export interface LocationService { deleteLocation(id: string): Promise; } -export interface LocationStore { - createLocation(spec: LocationSpec): Promise; - listLocations(): Promise; - getLocation(id: string): Promise; - deleteLocation(id: string): Promise; -} - -export interface CatalogProcessingEngine { - start(): Promise; - stop(): Promise; -} - /** * Options for requesting a refresh of entities in the catalog. * @@ -61,15 +48,9 @@ export interface RefreshService { refresh(options: RefreshOptions): Promise; } -export type EntityProviderMutation = - | { type: 'full'; entities: DeferredEntity[] } - | { type: 'delta'; added: DeferredEntity[]; removed: DeferredEntity[] }; - -export interface EntityProviderConnection { - applyMutation(mutation: EntityProviderMutation): Promise; -} - -export interface EntityProvider { - getProviderName(): string; - connect(connection: EntityProviderConnection): Promise; +export interface LocationStore { + createLocation(spec: LocationSpec): Promise; + listLocations(): Promise; + getLocation(id: string): Promise; + deleteLocation(id: string): Promise; } diff --git a/plugins/catalog-backend/src/next/stitching/Stitcher.test.ts b/plugins/catalog-backend/src/stitching/Stitcher.test.ts similarity index 100% rename from plugins/catalog-backend/src/next/stitching/Stitcher.test.ts rename to plugins/catalog-backend/src/stitching/Stitcher.test.ts diff --git a/plugins/catalog-backend/src/next/stitching/Stitcher.ts b/plugins/catalog-backend/src/stitching/Stitcher.ts similarity index 100% rename from plugins/catalog-backend/src/next/stitching/Stitcher.ts rename to plugins/catalog-backend/src/stitching/Stitcher.ts diff --git a/plugins/catalog-backend/src/next/stitching/buildEntitySearch.test.ts b/plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts similarity index 100% rename from plugins/catalog-backend/src/next/stitching/buildEntitySearch.test.ts rename to plugins/catalog-backend/src/stitching/buildEntitySearch.test.ts diff --git a/plugins/catalog-backend/src/next/stitching/buildEntitySearch.ts b/plugins/catalog-backend/src/stitching/buildEntitySearch.ts similarity index 100% rename from plugins/catalog-backend/src/next/stitching/buildEntitySearch.ts rename to plugins/catalog-backend/src/stitching/buildEntitySearch.ts diff --git a/plugins/catalog-backend/src/next/stitching/index.ts b/plugins/catalog-backend/src/stitching/index.ts similarity index 100% rename from plugins/catalog-backend/src/next/stitching/index.ts rename to plugins/catalog-backend/src/stitching/index.ts diff --git a/plugins/catalog-backend/src/next/stitching/util.ts b/plugins/catalog-backend/src/stitching/util.ts similarity index 100% rename from plugins/catalog-backend/src/next/stitching/util.ts rename to plugins/catalog-backend/src/stitching/util.ts diff --git a/plugins/catalog-backend/src/next/util.ts b/plugins/catalog-backend/src/util/conversion.ts similarity index 100% rename from plugins/catalog-backend/src/next/util.ts rename to plugins/catalog-backend/src/util/conversion.ts diff --git a/plugins/catalog-backend/src/next/metrics.ts b/plugins/catalog-backend/src/util/metrics.ts similarity index 100% rename from plugins/catalog-backend/src/next/metrics.ts rename to plugins/catalog-backend/src/util/metrics.ts diff --git a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx index f0844c265c..2618fab57a 100644 --- a/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx +++ b/plugins/catalog-import/src/components/StepPrepareCreatePullRequest/PreviewCatalogInfoComponent.test.tsx @@ -46,7 +46,7 @@ const entities: Entity[] = [ describe('', () => { it('renders without exploding', async () => { - const { getByText } = render( + const { getByText, findByText } = render( ', () => { ); const repositoryUrl = getByText('http://my-repository/a/catalog-info.yaml'); - const kindText = getByText('Kind_2'); + const kindText = await findByText('Kind_2'); expect(repositoryUrl).toBeInTheDocument(); expect(repositoryUrl).toBeVisible(); expect(kindText).toBeInTheDocument(); diff --git a/plugins/catalog-react/api-report.md b/plugins/catalog-react/api-report.md index 7f50e87e03..ce7282276e 100644 --- a/plugins/catalog-react/api-report.md +++ b/plugins/catalog-react/api-report.md @@ -257,13 +257,14 @@ export const EntityRefLink: React_2.ForwardRefExoticComponent< | 'children' | 'key' | 'id' + | 'className' | 'classes' + | 'innerRef' | 'defaultChecked' | 'defaultValue' | 'suppressContentEditableWarning' | 'suppressHydrationWarning' | 'accessKey' - | 'className' | 'contentEditable' | 'contextMenu' | 'draggable' @@ -504,7 +505,6 @@ export const EntityRefLink: React_2.ForwardRefExoticComponent< | 'onTransitionEndCapture' | 'component' | 'variant' - | 'innerRef' | 'download' | 'href' | 'hrefLang' diff --git a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx index 628526e9ab..750692ed2e 100644 --- a/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx +++ b/plugins/catalog-react/src/components/EntityLifecyclePicker/EntityLifecyclePicker.tsx @@ -19,6 +19,7 @@ import { Box, Checkbox, FormControlLabel, + makeStyles, TextField, Typography, } from '@material-ui/core'; @@ -30,10 +31,20 @@ import React, { useEffect, useMemo, useState } from 'react'; import { useEntityListProvider } from '../../hooks/useEntityListProvider'; import { EntityLifecycleFilter } from '../../filters'; +const useStyles = makeStyles( + { + input: {}, + }, + { + name: 'CatalogReactEntityLifecyclePicker', + }, +); + const icon = ; const checkedIcon = ; export const EntityLifecyclePicker = () => { + const classes = useStyles(); const { updateFilters, backendEntities, filters, queryParameters } = useEntityListProvider(); @@ -91,7 +102,9 @@ export const EntityLifecyclePicker = () => { )} size="small" popupIcon={} - renderInput={params => } + renderInput={params => ( + + )} /> ); diff --git a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx index 49c950f57e..dbf6a33164 100644 --- a/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx +++ b/plugins/catalog-react/src/components/EntityOwnerPicker/EntityOwnerPicker.tsx @@ -19,6 +19,7 @@ import { Box, Checkbox, FormControlLabel, + makeStyles, TextField, Typography, } from '@material-ui/core'; @@ -32,10 +33,20 @@ import { EntityOwnerFilter } from '../../filters'; import { getEntityRelations } from '../../utils'; import { formatEntityRefTitle } from '../EntityRefLink'; +const useStyles = makeStyles( + { + input: {}, + }, + { + name: 'CatalogReactEntityOwnerPicker', + }, +); + const icon = ; const checkedIcon = ; export const EntityOwnerPicker = () => { + const classes = useStyles(); const { updateFilters, backendEntities, filters, queryParameters } = useEntityListProvider(); @@ -95,7 +106,9 @@ export const EntityOwnerPicker = () => { )} size="small" popupIcon={} - renderInput={params => } + renderInput={params => ( + + )} /> ); diff --git a/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx b/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx index 9fd30b5182..3a848591a3 100644 --- a/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx +++ b/plugins/catalog-react/src/components/EntitySearchBar/EntitySearchBar.tsx @@ -29,15 +29,21 @@ import { useDebounce } from 'react-use'; import { useEntityListProvider } from '../../hooks/useEntityListProvider'; import { EntityTextFilter } from '../../filters'; -const useStyles = makeStyles(_theme => ({ - searchToolbar: { - paddingLeft: 0, - paddingRight: 0, +const useStyles = makeStyles( + _theme => ({ + searchToolbar: { + paddingLeft: 0, + paddingRight: 0, + }, + input: {}, + }), + { + name: 'CatalogReactEntitySearchBar', }, -})); +); export const EntitySearchBar = () => { - const styles = useStyles(); + const classes = useStyles(); const { filters, updateFilters } = useEntityListProvider(); const [search, setSearch] = useState(filters.text?.value ?? ''); @@ -53,10 +59,11 @@ export const EntitySearchBar = () => { ); return ( - + setSearch(event.target.value)} diff --git a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx index 64c80d1cde..9e00f7e7b0 100644 --- a/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx +++ b/plugins/catalog-react/src/components/EntityTagPicker/EntityTagPicker.tsx @@ -19,6 +19,7 @@ import { Box, Checkbox, FormControlLabel, + makeStyles, TextField, Typography, } from '@material-ui/core'; @@ -30,10 +31,20 @@ import React, { useEffect, useMemo, useState } from 'react'; import { useEntityListProvider } from '../../hooks/useEntityListProvider'; import { EntityTagFilter } from '../../filters'; +const useStyles = makeStyles( + { + input: {}, + }, + { + name: 'CatalogReactEntityTagPicker', + }, +); + const icon = ; const checkedIcon = ; export const EntityTagPicker = () => { + const classes = useStyles(); const { updateFilters, backendEntities, filters, queryParameters } = useEntityListProvider(); @@ -87,7 +98,9 @@ export const EntityTagPicker = () => { )} size="small" popupIcon={} - renderInput={params => } + renderInput={params => ( + + )} /> ); diff --git a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx index bfc55142a6..f861355762 100644 --- a/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx +++ b/plugins/catalog-react/src/components/UserListPicker/UserListPicker.tsx @@ -43,29 +43,34 @@ import { import { UserListFilterKind } from '../../types'; import { reduceEntityFilters } from '../../utils'; -const useStyles = makeStyles(theme => ({ - root: { - backgroundColor: 'rgba(0, 0, 0, .11)', - boxShadow: 'none', - margin: theme.spacing(1, 0, 1, 0), +const useStyles = makeStyles( + theme => ({ + root: { + backgroundColor: 'rgba(0, 0, 0, .11)', + boxShadow: 'none', + margin: theme.spacing(1, 0, 1, 0), + }, + title: { + margin: theme.spacing(1, 0, 0, 1), + textTransform: 'uppercase', + fontSize: 12, + fontWeight: 'bold', + }, + listIcon: { + minWidth: 30, + color: theme.palette.text.primary, + }, + menuItem: { + minHeight: theme.spacing(6), + }, + groupWrapper: { + margin: theme.spacing(1, 1, 2, 1), + }, + }), + { + name: 'CatalogReactUserListPicker', }, - title: { - margin: theme.spacing(1, 0, 0, 1), - textTransform: 'uppercase', - fontSize: 12, - fontWeight: 'bold', - }, - listIcon: { - minWidth: 30, - color: theme.palette.text.primary, - }, - menuItem: { - minHeight: theme.spacing(6), - }, - groupWrapper: { - margin: theme.spacing(1, 1, 2, 1), - }, -})); +); export type ButtonGroup = { name: string; diff --git a/plugins/catalog/api-report.md b/plugins/catalog/api-report.md index 4937a3eb86..2be7fc8575 100644 --- a/plugins/catalog/api-report.md +++ b/plugins/catalog/api-report.md @@ -23,10 +23,12 @@ import { IconComponent } from '@backstage/core-plugin-api'; import { IdentityApi } from '@backstage/core-plugin-api'; import { InfoCardVariants } from '@backstage/core-components'; import { Location as Location_2 } from '@backstage/catalog-model'; +import { Overrides } from '@material-ui/core/styles/overrides'; import { PropsWithChildren } from 'react'; import { default as React_2 } from 'react'; import { ReactNode } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; +import { StyleRules } from '@material-ui/core/styles/withStyles'; import { TableColumn } from '@backstage/core-components'; import { TableProps } from '@backstage/core-components'; import { TabProps } from '@material-ui/core'; @@ -55,6 +57,13 @@ export const AboutField: ({ children, }: Props_2) => JSX.Element; +// @public (undocumented) +export type BackstageOverrides = Overrides & { + [Name in keyof PluginCatalogComponentsNameToClassKey]?: Partial< + StyleRules + >; +}; + // Warning: (ae-missing-release-tag) "CatalogClientWrapper" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @@ -323,6 +332,9 @@ export const EntityLinksCard: ({ variant?: 'gridItem' | undefined; }) => JSX.Element; +// @public (undocumented) +export type EntityLinksEmptyStateClassKey = 'code'; + // Warning: (ae-missing-release-tag) "EntityListContainer" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public (undocumented) @@ -424,6 +436,12 @@ export function isNamespace(namespace: string): (entity: Entity) => boolean; // @public (undocumented) export const isOrphan: (entity: Entity) => boolean; +// @public (undocumented) +export type PluginCatalogComponentsNameToClassKey = { + PluginCatalogEntityLinksEmptyState: EntityLinksEmptyStateClassKey; + PluginCatalogSystemDiagramCard: SystemDiagramCardClassKey; +}; + // Warning: (ae-missing-release-tag) "Router" is exported by the package, but it is missing a release tag (@alpha, @beta, @public, or @internal) // // @public @deprecated (undocumented) @@ -433,6 +451,14 @@ export const Router: ({ EntityPage?: React_2.ComponentType<{}> | undefined; }) => JSX.Element; +// @public (undocumented) +export type SystemDiagramCardClassKey = + | 'domainNode' + | 'systemNode' + | 'componentNode' + | 'apiNode' + | 'resourceNode'; + // Warnings were encountered during analysis: // // src/components/CatalogTable/CatalogTable.d.ts:10:5 - (ae-forgotten-export) The symbol "CatalogTableProps" needs to be exported by the entry point index.d.ts diff --git a/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx b/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx index b0e8ee5d74..54325ffb5d 100644 --- a/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx +++ b/plugins/catalog/src/components/EntityLinksCard/EntityLinksEmptyState.tsx @@ -26,13 +26,19 @@ const ENTITY_YAML = `metadata: title: My Dashboard icon: dashboard`; -const useStyles = makeStyles(theme => ({ - code: { - borderRadius: 6, - margin: `${theme.spacing(2)}px 0px`, - background: theme.palette.type === 'dark' ? '#444' : '#fff', - }, -})); +/** @public */ +export type EntityLinksEmptyStateClassKey = 'code'; + +const useStyles = makeStyles( + theme => ({ + code: { + borderRadius: 6, + margin: `${theme.spacing(2)}px 0px`, + background: theme.palette.type === 'dark' ? '#444' : '#fff', + }, + }), + { name: 'PluginCatalogEntityLinksEmptyState' }, +); export const EntityLinksEmptyState = () => { const classes = useStyles(); diff --git a/plugins/catalog/src/components/EntityLinksCard/index.ts b/plugins/catalog/src/components/EntityLinksCard/index.ts index 04c30c0f68..fc53904a47 100644 --- a/plugins/catalog/src/components/EntityLinksCard/index.ts +++ b/plugins/catalog/src/components/EntityLinksCard/index.ts @@ -15,3 +15,4 @@ */ export { EntityLinksCard } from './EntityLinksCard'; +export type { EntityLinksEmptyStateClassKey } from './EntityLinksEmptyState'; diff --git a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx index b3326abaab..984ae9f982 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx +++ b/plugins/catalog/src/components/SystemDiagramCard/SystemDiagramCard.tsx @@ -46,28 +46,39 @@ import { import { useApi, useRouteRef } from '@backstage/core-plugin-api'; -const useStyles = makeStyles((theme: BackstageTheme) => ({ - domainNode: { - fill: theme.palette.primary.main, - stroke: theme.palette.border, - }, - systemNode: { - fill: 'coral', - stroke: theme.palette.border, - }, - componentNode: { - fill: 'yellowgreen', - stroke: theme.palette.border, - }, - apiNode: { - fill: theme.palette.gold, - stroke: theme.palette.border, - }, - resourceNode: { - fill: 'grey', - stroke: theme.palette.border, - }, -})); +/** @public */ +export type SystemDiagramCardClassKey = + | 'domainNode' + | 'systemNode' + | 'componentNode' + | 'apiNode' + | 'resourceNode'; + +const useStyles = makeStyles( + (theme: BackstageTheme) => ({ + domainNode: { + fill: theme.palette.primary.main, + stroke: theme.palette.border, + }, + systemNode: { + fill: 'coral', + stroke: theme.palette.border, + }, + componentNode: { + fill: 'yellowgreen', + stroke: theme.palette.border, + }, + apiNode: { + fill: theme.palette.gold, + stroke: theme.palette.border, + }, + resourceNode: { + fill: 'grey', + stroke: theme.palette.border, + }, + }), + { name: 'PluginCatalogSystemDiagramCard' }, +); // Simplifies the diagram output by hiding the default namespace and kind function readableEntityName( diff --git a/plugins/catalog/src/components/SystemDiagramCard/index.ts b/plugins/catalog/src/components/SystemDiagramCard/index.ts index 4c1427c838..bc9ed6309d 100644 --- a/plugins/catalog/src/components/SystemDiagramCard/index.ts +++ b/plugins/catalog/src/components/SystemDiagramCard/index.ts @@ -15,3 +15,4 @@ */ export { SystemDiagramCard } from './SystemDiagramCard'; +export type { SystemDiagramCardClassKey } from './SystemDiagramCard'; diff --git a/plugins/catalog/src/index.ts b/plugins/catalog/src/index.ts index 54f4da5e7e..d804bbaf83 100644 --- a/plugins/catalog/src/index.ts +++ b/plugins/catalog/src/index.ts @@ -33,6 +33,7 @@ export * from './components/EntityProcessingErrorsPanel'; export * from './components/EntityPageLayout'; export * from './components/EntitySwitch'; export * from './components/FilteredEntityLayout'; +export * from './overridableComponents'; export { Router } from './components/Router'; export { CatalogEntityPage, @@ -50,3 +51,6 @@ export { EntityLinksCard, EntitySystemDiagramCard, } from './plugin'; + +export type { EntityLinksEmptyStateClassKey } from './components/EntityLinksCard'; +export type { SystemDiagramCardClassKey } from './components/SystemDiagramCard'; diff --git a/plugins/catalog/src/overridableComponents.ts b/plugins/catalog/src/overridableComponents.ts new file mode 100644 index 0000000000..e76aafbb68 --- /dev/null +++ b/plugins/catalog/src/overridableComponents.ts @@ -0,0 +1,33 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { Overrides } from '@material-ui/core/styles/overrides'; +import { StyleRules } from '@material-ui/core/styles/withStyles'; + +import { EntityLinksEmptyStateClassKey } from './components/EntityLinksCard'; +import { SystemDiagramCardClassKey } from './components/SystemDiagramCard'; + +/** @public */ +export type PluginCatalogComponentsNameToClassKey = { + PluginCatalogEntityLinksEmptyState: EntityLinksEmptyStateClassKey; + PluginCatalogSystemDiagramCard: SystemDiagramCardClassKey; +}; + +/** @public */ +export type BackstageOverrides = Overrides & { + [Name in keyof PluginCatalogComponentsNameToClassKey]?: Partial< + StyleRules + >; +}; diff --git a/plugins/home/api-report.md b/plugins/home/api-report.md index db7631290d..a1cd98124a 100644 --- a/plugins/home/api-report.md +++ b/plugins/home/api-report.md @@ -122,6 +122,9 @@ export const SettingsModal: ({ children: JSX.Element; }) => JSX.Element; +// @public +export const WelcomeTitle: () => JSX.Element; + // Warnings were encountered during analysis: // // src/extensions.d.ts:16:5 - (ae-forgotten-export) The symbol "ComponentParts" needs to be exported by the entry point index.d.ts diff --git a/plugins/home/src/componentRenderers/ComponentTabs/ComponentTabs.test.tsx b/plugins/home/src/componentRenderers/ComponentTabs/ComponentTabs.test.tsx new file mode 100644 index 0000000000..96ab37a8aa --- /dev/null +++ b/plugins/home/src/componentRenderers/ComponentTabs/ComponentTabs.test.tsx @@ -0,0 +1,76 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { render } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; +import React from 'react'; +import { ComponentTabs } from './ComponentTabs'; + +describe('', () => { + test('should render tabs without exploding', () => { + const { getByText } = render( + <>ContentA, + }, + { + label: 'TabB', + Component: () => <>ContentB, + }, + ]} + />, + ); + + expect(getByText('TabA')).toBeInTheDocument(); + expect(getByText('TabB')).toBeInTheDocument(); + + expect(getByText('ContentA')).toBeInTheDocument(); + expect(getByText('ContentB')).toHaveStyle({ + display: 'none', + }); + }); + + test('should switch tab on click', () => { + const { getByText } = render( + <>ContentA, + }, + { + label: 'TabB', + Component: () => <>ContentB, + }, + ]} + />, + ); + + expect(getByText('ContentB')).toHaveStyle({ + display: 'none', + }); + + userEvent.click(getByText('TabB')); + + expect(getByText('ContentA')).toHaveStyle({ + display: 'none', + }); + }); +}); diff --git a/plugins/home/src/componentRenderers/ComponentTabs/ComponentTabs.tsx b/plugins/home/src/componentRenderers/ComponentTabs/ComponentTabs.tsx index f404a80980..d6d3561fe1 100644 --- a/plugins/home/src/componentRenderers/ComponentTabs/ComponentTabs.tsx +++ b/plugins/home/src/componentRenderers/ComponentTabs/ComponentTabs.tsx @@ -44,7 +44,10 @@ export const ComponentTabs = ({ ))} {tabs.map(({ Component }, idx) => ( -
+
))} diff --git a/plugins/home/src/homePageComponents/WelcomeTitle/WelcomeTitle.test.tsx b/plugins/home/src/homePageComponents/WelcomeTitle/WelcomeTitle.test.tsx new file mode 100644 index 0000000000..839ecdbae1 --- /dev/null +++ b/plugins/home/src/homePageComponents/WelcomeTitle/WelcomeTitle.test.tsx @@ -0,0 +1,32 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { renderInTestApp } from '@backstage/test-utils'; +import React from 'react'; +import { WelcomeTitle } from './WelcomeTitle'; + +describe('', () => { + afterEach(() => jest.resetAllMocks()); + + test('should greet user', async () => { + jest + .spyOn(global.Date, 'now') + .mockImplementation(() => new Date('1970-01-01T23:00:00').valueOf()); + + const { getByText } = await renderInTestApp(); + + expect(getByText(/Get some rest, Guest/)).toBeInTheDocument(); + }); +}); diff --git a/plugins/home/src/homePageComponents/WelcomeTitle/WelcomeTitle.tsx b/plugins/home/src/homePageComponents/WelcomeTitle/WelcomeTitle.tsx new file mode 100644 index 0000000000..04ec7e1673 --- /dev/null +++ b/plugins/home/src/homePageComponents/WelcomeTitle/WelcomeTitle.tsx @@ -0,0 +1,32 @@ +/* + * Copyright 2021 The Backstage Authors + * + * 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 { identityApiRef, useApi } from '@backstage/core-plugin-api'; +import { Tooltip } from '@material-ui/core'; +import React, { useMemo } from 'react'; +import { getTimeBasedGreeting } from './timeUtil'; + +export const WelcomeTitle = () => { + const identityApi = useApi(identityApiRef); + const profile = identityApi.getProfile(); + const userId = identityApi.getUserId(); + const greeting = useMemo(() => getTimeBasedGreeting(), []); + + return ( + + {`${greeting.greeting}, ${profile.displayName || userId}!`} + + ); +}; diff --git a/plugins/catalog-backend/src/next/Context/index.ts b/plugins/home/src/homePageComponents/WelcomeTitle/index.ts similarity index 71% rename from plugins/catalog-backend/src/next/Context/index.ts rename to plugins/home/src/homePageComponents/WelcomeTitle/index.ts index 822edba478..ca237511e7 100644 --- a/plugins/catalog-backend/src/next/Context/index.ts +++ b/plugins/home/src/homePageComponents/WelcomeTitle/index.ts @@ -13,9 +13,4 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - -export { BackgroundContext } from './BackgroundContext'; -export { ContextWithValue } from './ContextWithValue'; -export { TransactionValue } from './TransactionValue'; -export { ContextKey } from './types'; -export type { Context } from './types'; +export { WelcomeTitle } from './WelcomeTitle'; diff --git a/plugins/welcome/src/utils/locales/goodAfternoon.locales.json b/plugins/home/src/homePageComponents/WelcomeTitle/locales/goodAfternoon.locales.json similarity index 100% rename from plugins/welcome/src/utils/locales/goodAfternoon.locales.json rename to plugins/home/src/homePageComponents/WelcomeTitle/locales/goodAfternoon.locales.json diff --git a/plugins/welcome/src/utils/locales/goodEvening.locales.json b/plugins/home/src/homePageComponents/WelcomeTitle/locales/goodEvening.locales.json similarity index 100% rename from plugins/welcome/src/utils/locales/goodEvening.locales.json rename to plugins/home/src/homePageComponents/WelcomeTitle/locales/goodEvening.locales.json diff --git a/plugins/welcome/src/utils/locales/goodMorning.locales.json b/plugins/home/src/homePageComponents/WelcomeTitle/locales/goodMorning.locales.json similarity index 100% rename from plugins/welcome/src/utils/locales/goodMorning.locales.json rename to plugins/home/src/homePageComponents/WelcomeTitle/locales/goodMorning.locales.json diff --git a/plugins/welcome/src/utils/timeUtil.test.js b/plugins/home/src/homePageComponents/WelcomeTitle/timeUtil.test.ts similarity index 55% rename from plugins/welcome/src/utils/timeUtil.test.js rename to plugins/home/src/homePageComponents/WelcomeTitle/timeUtil.test.ts index 2abb03152f..77eb6677ca 100644 --- a/plugins/welcome/src/utils/timeUtil.test.js +++ b/plugins/home/src/homePageComponents/WelcomeTitle/timeUtil.test.ts @@ -16,16 +16,20 @@ import { getTimeBasedGreeting } from './timeUtil'; -it('has greeting and language', () => { - const greeting = getTimeBasedGreeting(); - expect(greeting).toHaveProperty('greeting'); - expect(greeting).toHaveProperty('language'); -}); +describe('getTimeBasedGreeting', () => { + afterEach(() => jest.resetAllMocks()); -it('greets late at night', () => { - jest - .spyOn(global.Date, 'now') - .mockImplementationOnce(() => new Date('1970-01-01T23:00:00').valueOf()); - const greeting = getTimeBasedGreeting(); - expect(greeting.greeting).toBe('Get some rest'); + it('has greeting and language', () => { + const greeting = getTimeBasedGreeting(); + expect(greeting).toHaveProperty('greeting'); + expect(greeting).toHaveProperty('language'); + }); + + it('greets late at night', () => { + jest + .spyOn(global.Date, 'now') + .mockImplementationOnce(() => new Date('1970-01-01T23:00:00').valueOf()); + const greeting = getTimeBasedGreeting(); + expect(greeting.greeting).toBe('Get some rest'); + }); }); diff --git a/plugins/welcome/src/utils/timeUtil.js b/plugins/home/src/homePageComponents/WelcomeTitle/timeUtil.ts similarity index 83% rename from plugins/welcome/src/utils/timeUtil.js rename to plugins/home/src/homePageComponents/WelcomeTitle/timeUtil.ts index 93f4379d8e..8df7703b44 100644 --- a/plugins/welcome/src/utils/timeUtil.js +++ b/plugins/home/src/homePageComponents/WelcomeTitle/timeUtil.ts @@ -18,12 +18,12 @@ import goodMorning from './locales/goodMorning.locales.json'; import goodAfternoon from './locales/goodAfternoon.locales.json'; import goodEvening from './locales/goodEvening.locales.json'; -// Select a large random integer at startup, to prevent the greetings to change every time the user -// navigates. +// Select a large random integer at startup, to prevent the greetings to change +// every time the user navigates. const greetingRandomSeed = Math.floor(Math.random() * 1000000); -export function getTimeBasedGreeting() { - const random = array => array[greetingRandomSeed % array.length]; +export function getTimeBasedGreeting(): { language: string; greeting: string } { + const random = (array: string[]) => array[greetingRandomSeed % array.length]; const currentHour = new Date(Date.now()).getHours(); if (currentHour >= 23) { @@ -32,7 +32,7 @@ export function getTimeBasedGreeting() { greeting: 'Get some rest', }; } - const timeOfDay = hour => { + const timeOfDay = (hour: number): { [language: string]: string } => { if (hour < 12) return goodMorning; if (hour < 17) return goodAfternoon; return goodEvening; diff --git a/plugins/home/src/index.ts b/plugins/home/src/index.ts index 0dacda7a01..0004cf5a23 100644 --- a/plugins/home/src/index.ts +++ b/plugins/home/src/index.ts @@ -27,6 +27,7 @@ export { ComponentAccordion, ComponentTabs, ComponentTab, + WelcomeTitle, } from './plugin'; export { SettingsModal } from './components'; export { createCardExtension } from './extensions'; diff --git a/plugins/home/src/plugin.ts b/plugins/home/src/plugin.ts index 22ece00362..d67ea846a5 100644 --- a/plugins/home/src/plugin.ts +++ b/plugins/home/src/plugin.ts @@ -64,6 +64,20 @@ export const ComponentTab = homePlugin.provide( }), ); +/** + * A component to display a playful greeting for the user. + * + * @public + */ +export const WelcomeTitle = homePlugin.provide( + createComponentExtension({ + component: { + lazy: () => + import('./homePageComponents/WelcomeTitle').then(m => m.WelcomeTitle), + }, + }), +); + export const HomePageRandomJoke = homePlugin.provide( createCardExtension<{ defaultCategory?: 'any' | 'programming' }>({ title: 'Random Joke', diff --git a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts index d676af56ca..4befec5a81 100644 --- a/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts +++ b/plugins/scaffolder-backend/src/scaffolder/actions/builtin/fetch/template.test.ts @@ -15,10 +15,14 @@ */ import os from 'os'; -import { join as joinPath, resolve as resolvePath } from 'path'; +import { join as joinPath } from 'path'; import fs from 'fs-extra'; import mockFs from 'mock-fs'; -import { getVoidLogger, UrlReader } from '@backstage/backend-common'; +import { + getVoidLogger, + resolvePackagePath, + UrlReader, +} from '@backstage/backend-common'; import { ScmIntegrations } from '@backstage/integration'; import { PassThrough } from 'stream'; import { fetchContents } from './helpers'; @@ -30,9 +34,9 @@ jest.mock('./helpers', () => ({ })); const aBinaryFile = fs.readFileSync( - resolvePath( - 'src', - '../fixtures/test-nested-template/public/react-logo192.png', + resolvePackagePath( + '@backstage/plugin-scaffolder-backend', + 'fixtures/test-nested-template/public/react-logo192.png', ), ); diff --git a/yarn.lock b/yarn.lock index eba5fb856f..1a0caad7e9 100644 --- a/yarn.lock +++ b/yarn.lock @@ -2105,7 +2105,7 @@ dependencies: regenerator-runtime "^0.13.4" -"@babel/runtime@^7.2.0": +"@babel/runtime@^7.12.1", "@babel/runtime@^7.2.0": version "7.15.4" resolved "https://registry.npmjs.org/@babel/runtime/-/runtime-7.15.4.tgz#fd17d16bfdf878e6dd02d19753a39fa8a8d9c84a" integrity sha512-99catp6bHCaxr4sJ/DbTGgHS4+Rs2RVd2g7iOap6SLGPDknRK9ztKNsE/Fg6QhSeh1FGE5f6gHGQmvvn3I3xhw== @@ -3686,18 +3686,6 @@ underscore "^1.9.1" ws "^7.3.1" -"@kyleshockey/object-assign-deep@^0.4.2": - version "0.4.2" - resolved "https://registry.npmjs.org/@kyleshockey/object-assign-deep/-/object-assign-deep-0.4.2.tgz#84900f0eefc372798f4751b5262830b8208922ec" - integrity sha1-hJAPDu/DcnmPR1G1JigwuCCJIuw= - -"@kyleshockey/xml@^1.0.2": - version "1.0.2" - resolved "https://registry.npmjs.org/@kyleshockey/xml/-/xml-1.0.2.tgz#81fad3d7c33da2ba2639db095db3db24c2921f70" - integrity sha512-iMo32MPLcI9cPxs3YL5kmKxKgDmkSZDCFEqIT5eRk7d/Ll8r4X3SwGYSigzALd6+RHWlFEmjL1QyaQ15xDZFlw== - dependencies: - stream "^0.0.2" - "@lerna/add@4.0.0": version "4.0.0" resolved "https://registry.npmjs.org/@lerna/add/-/add-4.0.0.tgz#c36f57d132502a57b9e7058d1548b7a565ef183f" @@ -4960,11 +4948,6 @@ "@octokit/types" "^6.12.2" btoa-lite "^1.0.0" -"@octokit/openapi-types@^2.2.0": - version "2.2.0" - resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-2.2.0.tgz#123e0438a0bc718ccdac3b5a2e69b3dd00daa85b" - integrity sha512-274lNUDonw10kT8wHg8fCcUc1ZjZHbWv0/TbAwb0ojhBQqZYc1cQ/4yqTVTtPMDeZ//g7xVEYe/s3vURkRghPg== - "@octokit/openapi-types@^7.3.2": version "7.3.2" resolved "https://registry.npmjs.org/@octokit/openapi-types/-/openapi-types-7.3.2.tgz#065ce49b338043ec7f741316ce06afd4d459d944" @@ -6807,6 +6790,14 @@ dependencies: highlight.js "^10.1.0" +"@types/hoist-non-react-statics@^3.3.0": + version "3.3.1" + resolved "https://registry.npmjs.org/@types/hoist-non-react-statics/-/hoist-non-react-statics-3.3.1.tgz#1124aafe5118cb591977aeb1ceaaed1070eb039f" + integrity sha512-iMIqiko6ooLrTh1joXodJK5X9xeEALT1kM5G3ZLhD3hszxBdIEd5C75U834D9mLcINgD4OyZf5uQXjkuYydWvA== + dependencies: + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + "@types/html-minifier-terser@^5.0.0": version "5.1.0" resolved "https://registry.npmjs.org/@types/html-minifier-terser/-/html-minifier-terser-5.1.0.tgz#551a4589b6ee2cc9c1dff08056128aec29b94880" @@ -7315,6 +7306,16 @@ "@types/react" "*" immutable ">=3.8.2" +"@types/react-redux@^7.1.16": + version "7.1.19" + resolved "https://registry.npmjs.org/@types/react-redux/-/react-redux-7.1.19.tgz#477bd0a9b01bae6d6bf809418cdfa7d3c16d4c62" + integrity sha512-L37dSCT0aoJnCgpR8Iuginlbxoh7qhWOXiaDqEsxVMrER1CmVhFD+63NxgJeT4pkmEM28oX0NH4S4f+sXHTZjA== + dependencies: + "@types/hoist-non-react-statics" "^3.3.0" + "@types/react" "*" + hoist-non-react-statics "^3.3.0" + redux "^4.0.0" + "@types/react-sparklines@^1.7.0": version "1.7.0" resolved "https://registry.npmjs.org/@types/react-sparklines/-/react-sparklines-1.7.0.tgz#f956d0f7b0e746ad445ce1cd250fe81f8a384684" @@ -7373,13 +7374,6 @@ "@types/scheduler" "*" csstype "^3.0.2" -"@types/react@16.4.6": - version "16.4.6" - resolved "https://registry.npmjs.org/@types/react/-/react-16.4.6.tgz#5024957c6bcef4f02823accf5974faba2e54fada" - integrity sha512-9LDZdhsuKSc+DjY65SjBkA958oBWcTWSVWAd2cD9XqKBjhGw1KzAkRhWRw2eIsXvaIE/TOTjjKMFVC+JA1iU4g== - dependencies: - csstype "^2.2.0" - "@types/recharts@^1.8.14", "@types/recharts@^1.8.15": version "1.8.19" resolved "https://registry.npmjs.org/@types/recharts/-/recharts-1.8.19.tgz#047f72cf4c25df545aa1085fe3a085e58a2483c1" @@ -11431,14 +11425,6 @@ create-hmac@^1.1.0, create-hmac@^1.1.2, create-hmac@^1.1.4: safe-buffer "^5.0.1" sha.js "^2.4.8" -create-react-class@^15.5.1: - version "15.7.0" - resolved "https://registry.npmjs.org/create-react-class/-/create-react-class-15.7.0.tgz#7499d7ca2e69bb51d13faf59bd04f0c65a1d6c1e" - integrity sha512-QZv4sFWG9S5RUvkTYWbflxeZX+JG7Cz0Tn33rQBJ+WFQTqTfUTjMjiv9tnfXazjsO5r0KhPs+AqCjyrQX6h2ng== - dependencies: - loose-envify "^1.3.1" - object-assign "^4.1.1" - create-react-context@0.3.0: version "0.3.0" resolved "https://registry.npmjs.org/create-react-context/-/create-react-context-0.3.0.tgz#546dede9dc422def0d3fc2fe03afe0bc0f4f7d8c" @@ -11795,7 +11781,7 @@ cssstyle@^2.2.0: dependencies: cssom "~0.3.6" -csstype@^2.2.0, csstype@^2.5.2, csstype@^2.5.7, csstype@^2.6.7: +csstype@^2.5.2, csstype@^2.5.7, csstype@^2.6.7: version "2.6.17" resolved "https://registry.npmjs.org/csstype/-/csstype-2.6.17.tgz#4cf30eb87e1d1a005d8b6510f95292413f6a1c0e" integrity sha512-u1wmTI1jJGzCJzWndZo8mk4wnPTZd1eOIYTYvuEyOQGfmDl3TrabCCfKnOC86FZwW/9djqTl933UF/cS425i9A== @@ -12877,11 +12863,6 @@ elliptic@^6.0.0: minimalistic-assert "^1.0.1" minimalistic-crypto-utils "^1.0.1" -emitter-component@^1.1.1: - version "1.1.1" - resolved "https://registry.npmjs.org/emitter-component/-/emitter-component-1.1.1.tgz#065e2dbed6959bf470679edabeaf7981d1003ab6" - integrity sha1-Bl4tvtaVm/RwZ57avq95gdEAOrY= - emittery@^0.7.1: version "0.7.1" resolved "https://registry.npmjs.org/emittery/-/emittery-0.7.1.tgz#c02375a927a40948c0345cc903072597f5270451" @@ -13988,11 +13969,6 @@ fecha@^4.2.0: resolved "https://registry.npmjs.org/fecha/-/fecha-4.2.0.tgz#3ffb6395453e3f3efff850404f0a59b6747f5f41" integrity sha512-aN3pcx/DSmtyoovUudctc8+6Hl4T+hI9GBBHLjA76jdZl7+b1sgh5g4k+u/GL3dTy1/pnYzKp69FpJ0OicE3Wg== -fetch-blob@2.1.2: - version "2.1.2" - resolved "https://registry.npmjs.org/fetch-blob/-/fetch-blob-2.1.2.tgz#a7805db1361bd44c1ef62bb57fb5fe8ea173ef3c" - integrity sha512-YKqtUDwqLyfyMnmbw8XD6Q8j9i/HggKtPEI+pZ1+8bvheBu78biSmNaXWusx1TauGqtUUGx/cBb1mKdq2rLYow== - fetch-readablestream@^0.2.0: version "0.2.0" resolved "https://registry.npmjs.org/fetch-readablestream/-/fetch-readablestream-0.2.0.tgz#eaa6d1a76b12de2d4731a343393c6ccdcfe2c795" @@ -14305,10 +14281,10 @@ fork-ts-checker-webpack-plugin@^6.0.4: semver "^7.3.2" tapable "^1.0.0" -form-data-encoder@1.4.3, form-data-encoder@^1.0.1: - version "1.4.3" - resolved "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.4.3.tgz#b0975dbe5795676f211c0ff98e473eaf52b0db4a" - integrity sha512-ARLR/jJaj3+tlKkO7h1uvvjQcD6xCiKyg42hcG5Q4jv8uDa1IMPs81bM3BwI8BrqVEQxF9pX6tx0iLIzAvr31Q== +form-data-encoder@^1.4.3: + version "1.6.0" + resolved "https://registry.npmjs.org/form-data-encoder/-/form-data-encoder-1.6.0.tgz#9dd1f479836c1b1b47201667c68f8daafa800943" + integrity sha512-P97AVaOB8hZaniiKK3f46zxQcchQXI8EgBnX+2+719gLv5ZbDSf3J1XtIuAQ8xbGLU4vZYhy7xwhFtK8U5u9Nw== form-data@4.0.0, form-data@^4.0.0: version "4.0.0" @@ -14351,14 +14327,13 @@ format@^0.2.0: resolved "https://registry.npmjs.org/format/-/format-0.2.2.tgz#d6170107e9efdc4ed30c9dc39016df942b5cb58b" integrity sha1-1hcBB+nv3E7TDJ3DkBbflCtctYs= -formdata-node@^3.6.2: - version "3.7.0" - resolved "https://registry.npmjs.org/formdata-node/-/formdata-node-3.7.0.tgz#b58942e617639a0ebea57227cfff8332a4020760" - integrity sha512-O3y7XoWwE4zRvI5e1yVPDHyDGtEgGEI10KxTbQeMbEEt+imR7uxbL5Z4BCaHz5M09d1pkrFaqeYc8beAce4VSw== +formdata-node@^4.0.0: + version "4.3.0" + resolved "https://registry.npmjs.org/formdata-node/-/formdata-node-4.3.0.tgz#77be2add9092cbd1e1f4d35bc3293a89be117a04" + integrity sha512-TwqhWUZd2jB5l0kUhhcy1XYNsXq46NH6k60zmiu7xsxMztul+cCMuPSAQrSDV62zznhBKJdA9O+zeWj5i5Pbfg== dependencies: - fetch-blob "2.1.2" - form-data-encoder "1.4.3" node-domexception "1.0.0" + web-streams-polyfill "4.0.0-beta.1" formidable@^1.2.0, formidable@^1.2.2: version "1.2.2" @@ -15508,10 +15483,10 @@ highlight.js@^10.1.0, highlight.js@^10.1.1, highlight.js@^10.4.1, highlight.js@^ resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.2.tgz#89319b861edc66c48854ed1e6da21ea89f847360" integrity sha512-oFLl873u4usRM9K63j4ME9u3etNF0PLiJhSQ8rdfuL51Wn3zkD6drf9ZW0dOzjnZI22YYG24z30JcmfCZjMgYg== -highlight.js@~10.4.0: - version "10.4.1" - resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.4.1.tgz#d48fbcf4a9971c4361b3f95f302747afe19dbad0" - integrity sha512-yR5lWvNz7c85OhVAEAeFhVCc/GV4C30Fjzc/rCP0aCWzc1UUOPUk55dK/qdwTZHBvMZo+eZ2jpk62ndX/xMFlg== +highlight.js@~10.7.0: + version "10.7.3" + resolved "https://registry.npmjs.org/highlight.js/-/highlight.js-10.7.3.tgz#697272e3991356e40c3cac566a74eef681756531" + integrity sha512-tzcUFauisWKNHaRkN4Wjl/ZA07gENAjFl3J/c480dprkGTg5EQstgaNFqBfUqCq54kZRIEcreTsAgF/m2quD7A== history@^5.0.0: version "5.0.0" @@ -15968,7 +15943,7 @@ immer@^9.0.1: resolved "https://registry.npmjs.org/immer/-/immer-9.0.6.tgz#7a96bf2674d06c8143e327cbf73539388ddf1a73" integrity sha512-G95ivKpy+EvVAnAab4fVa4YGYn24J1SpEktnJX7JJ45Bd7xqME/SCplFzYFmTbrkwZbQ4xJK1xMTUYBkN6pWsQ== -immutable@>=3.8.2, immutable@^3.8.1, immutable@^3.8.2, immutable@^3.x.x: +immutable@>=3.8.2, immutable@^3.8.2, immutable@^3.x.x: version "3.8.2" resolved "https://registry.npmjs.org/immutable/-/immutable-3.8.2.tgz#c2439951455bb39913daf281376f1530e104adf3" integrity sha1-wkOZUUVbs5kT2vKBN28VMOEErfM= @@ -16225,7 +16200,7 @@ into-stream@^5.1.1: from2 "^2.3.0" p-is-promise "^3.0.0" -invariant@^2.0.0, invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: +invariant@^2.2.2, invariant@^2.2.3, invariant@^2.2.4: version "2.2.4" resolved "https://registry.npmjs.org/invariant/-/invariant-2.2.4.tgz#610f3c92c9359ce1db616e538008d23ff35158e6" integrity sha512-phJfQVBuaJM5raOpJjSfkiD6BpbCE4Ns//LaXl6wGYtUBY83nWS6Rf9tXm2e8VaK60JEjYldbPif/A2B1C2gNA== @@ -16448,7 +16423,7 @@ is-docker@^2.0.0, is-docker@^2.1.1: resolved "https://registry.npmjs.org/is-docker/-/is-docker-2.2.1.tgz#33eeabe23cfe86f14bde4408a02c0cfb853acdaa" integrity sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ== -is-dom@^1.0.0, is-dom@^1.0.9: +is-dom@^1.0.0: version "1.1.0" resolved "https://registry.npmjs.org/is-dom/-/is-dom-1.1.0.tgz#af1fced292742443bb59ca3f76ab5e80907b4e8a" integrity sha512-u82f6mvhYxRPKpw8V1N0W8ce1xXwOrQtgGcxl6UCL5zBmZu3is/18K0rR7uFCnMDuAsS/3W54mGL4vsaFUQlEQ== @@ -18585,11 +18560,6 @@ lodash-es@^4.17.15: resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.21.tgz#43e626c46e6591b7750beb2b50117390c609e3ee" integrity sha512-mKnC+QJ9pWVzv+C4/U3rRsHapFfHvQFoFB92e52xeyGMcX6/OlIl78je1u8vePzYZSkkogMPJ2yjxxsb89cxyw== -lodash-es@^4.2.1: - version "4.17.15" - resolved "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.15.tgz#21bd96839354412f23d7a10340e5eac6ee455d78" - integrity sha512-rlrc3yU3+JNOpZ9zj5pQtxnx2THmvRykwL4Xlxoa8I9lHBlVbbyPhgyPMioxVZ4NqyxaVVtaJnzsyOidQIhyyQ== - lodash._reinterpolate@^3.0.0: version "3.0.0" resolved "https://registry.npmjs.org/lodash._reinterpolate/-/lodash._reinterpolate-3.0.0.tgz#0ccf2d89166af03b3663c796538b75ac6e114d9d" @@ -18785,7 +18755,7 @@ lodash@4.17.15: resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.15.tgz#b447f6670a0455bbfeedd11392eff330ea097548" integrity sha512-8xOcRHvCjnocdS5cpwXQXVzmmh5e5+saE2QGoeQmbKmRS6J3VQppPOIt0MnmE+4xlZoumy0GPG0D0MVIQbNA1A== -lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.11, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@^4.2.1, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: +lodash@4.17.21, lodash@^4.17.10, lodash@^4.17.14, lodash@^4.17.15, lodash@^4.17.19, lodash@^4.17.20, lodash@^4.17.21, lodash@^4.17.4, lodash@^4.17.5, lodash@~4.17.0, lodash@~4.17.15, lodash@~4.17.4: version "4.17.21" resolved "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz#679591c564c3bffaae8454cf0b3df370c3d6911c" integrity sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg== @@ -18890,12 +18860,12 @@ lowercase-keys@^2.0.0: integrity sha512-tqNXrS78oMOE73NMxK4EMLQsQowWf8jKooH9g7xPavRT706R6bkQJ6DY2Te7QukaZsulxa30wQ7bk0pm4XiHmA== lowlight@^1.14.0, lowlight@^1.17.0: - version "1.17.0" - resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.17.0.tgz#a1143b2fba8239df8cd5893f9fe97aaf8465af4a" - integrity sha512-vmtBgYKD+QVNy7tIa7ulz5d//Il9R4MooOVh4nkOf9R9Cb/Dk5TXMSTieg/vDulkBkIWj59/BIlyFQxT9X1oAQ== + version "1.20.0" + resolved "https://registry.npmjs.org/lowlight/-/lowlight-1.20.0.tgz#ddb197d33462ad0d93bf19d17b6c301aa3941888" + integrity sha512-8Ktj+prEb1RoCPkEOrPMYUN/nCggB7qAWe3a7OpMjWQkh3l2RD5wKRQ+o8Q8YuI9RG/xs95waaI/E6ym/7NsTw== dependencies: fault "^1.0.0" - highlight.js "~10.4.0" + highlight.js "~10.7.0" lru-cache@^4.0.1, lru-cache@^4.1.3: version "4.1.5" @@ -21530,11 +21500,6 @@ pend@~1.2.0: resolved "https://registry.npmjs.org/pend/-/pend-1.2.0.tgz#7a57eb550a6783f9115331fcf4663d5c8e007a50" integrity sha1-elfrVQpng/kRUzH89GY9XI4AelA= -performance-now@^0.2.0: - version "0.2.0" - resolved "https://registry.npmjs.org/performance-now/-/performance-now-0.2.0.tgz#33ef30c5c77d4ea21c5a53869d91b56d8f2555e5" - integrity sha1-M+8wxcd9TqIcWlOGnZG1bY8lVeU= - performance-now@^2.1.0: version "2.1.0" resolved "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz#6309f4e0e5fa913ec1c69307ae364b4b377c9e7b" @@ -22723,7 +22688,7 @@ raf-schd@^4.0.2: resolved "https://registry.npmjs.org/raf-schd/-/raf-schd-4.0.2.tgz#bd44c708188f2e84c810bf55fcea9231bcaed8a0" integrity sha512-VhlMZmGy6A6hrkJWHLNTGl5gtgMUm+xfGza6wbwnE914yeQ5Ybm18vgM734RZhMgfw4tacUrWseGZlpUrrakEQ== -raf@^3.1.0, raf@^3.4.0, raf@^3.4.1: +raf@^3.4.0, raf@^3.4.1: version "3.4.1" resolved "https://registry.npmjs.org/raf/-/raf-3.4.1.tgz#0742e99a4a6552f445d73e3ee0328af0ff1ede39" integrity sha512-Sq4CW4QhwOHE8ucn6J34MqtZCeWFP2aQSmrlroYgqAV1PjStIhJXxYuTgUIfkEk7zTLjmIjLmU5q+fbD1NnOJA== @@ -22842,10 +22807,10 @@ react-copy-to-clipboard@5.0.3: copy-to-clipboard "^3" prop-types "^15.5.8" -react-debounce-input@^3.2.3: - version "3.2.3" - resolved "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.2.3.tgz#9e8c69771a621c81e8fe36b45ade49a95059cd87" - integrity sha512-7Bfjm9sxrtgB+IsSrdXoo4CVqKg7CbWC68dNhr8q7ZmY6C0AqtR524//SenHQWT+eeSG9DmSLWNWCUFSyaaWSQ== +react-debounce-input@=3.2.4: + version "3.2.4" + resolved "https://registry.npmjs.org/react-debounce-input/-/react-debounce-input-3.2.4.tgz#8204373a6498776536a2fcc7e467d054c3b729d4" + integrity sha512-fX70bNj0fLEYO2Zcvuh7eh9wOUQ29GIx6r8IxIJlc0i0mpUH++9ax0BhfAYfzndADli3RAMROrZQ014J01owrg== dependencies: lodash.debounce "^4" prop-types "^15.7.2" @@ -23001,23 +22966,12 @@ react-immutable-proptypes@2.2.0: dependencies: invariant "^2.2.2" -react-immutable-pure-component@^1.1.1: - version "1.2.3" - resolved "https://registry.npmjs.org/react-immutable-pure-component/-/react-immutable-pure-component-1.2.3.tgz#fa33638df68cfe9f73ccbee1d5861c17f3053f86" - integrity sha512-kNy2A/fDrSuR8TKwB+4ynmItmp1vgF87tWxxfmadwDYo2J3ANipHqTjDIBvJvJ7libvuh76jIbvmK0krjtKH1g== - optionalDependencies: - "@types/react" "16.4.6" +react-immutable-pure-component@^2.2.0: + version "2.2.2" + resolved "https://registry.npmjs.org/react-immutable-pure-component/-/react-immutable-pure-component-2.2.2.tgz#3014d3e20cd5a7a4db73b81f1f1464f4d351684b" + integrity sha512-vkgoMJUDqHZfXXnjVlG3keCxSO/U6WeDQ5/Sl0GK2cH8TOxEzQ5jXqDXHEL/jqk6fsNxV05oH5kD7VNMUE2k+A== -react-inspector@^2.3.0: - version "2.3.1" - resolved "https://registry.npmjs.org/react-inspector/-/react-inspector-2.3.1.tgz#f0eb7f520669b545b441af9d38ec6d706e5f649c" - integrity sha512-tUUK7t3KWgZEIUktOYko5Ic/oYwvjEvQUFAGC1UeMeDaQ5za2yZFtItJa2RTwBJB//NxPr000WQK6sEbqC6y0Q== - dependencies: - babel-runtime "^6.26.0" - is-dom "^1.0.9" - prop-types "^15.6.1" - -react-inspector@^5.1.0: +react-inspector@^5.1.0, react-inspector@^5.1.1: version "5.1.1" resolved "https://registry.npmjs.org/react-inspector/-/react-inspector-5.1.1.tgz#58476c78fde05d5055646ed8ec02030af42953c8" integrity sha512-GURDaYzoLbW8pMGXwYPDBIv6nqei4kK7LPRZ9q9HCZF54wqXz/dnylBp/kfE9XmekBhHvLDdcYeyIwSrvtOiWg== @@ -23026,7 +22980,7 @@ react-inspector@^5.1.0: is-dom "^1.0.0" prop-types "^15.0.0" -react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: +react-is@^16.13.1, react-is@^16.7.0, react-is@^16.8.0, react-is@^16.8.1, react-is@^16.8.4, react-is@^16.8.6, react-is@^16.9.0: version "16.13.1" resolved "https://registry.npmjs.org/react-is/-/react-is-16.13.1.tgz#789729a4dc36de2999dc156dd6c1d9c18cea56a4" integrity sha512-24e6ynE2H+OKt4kqsOvNd8kBpV65zoxbA4BVsEOB3ARVWQki/DHzaUoC5KuON/BiccDaCCTZBuOcfZs70kR8bQ== @@ -23072,15 +23026,6 @@ react-markdown@^5.0.2: unist-util-visit "^2.0.0" xtend "^4.0.1" -react-motion@^0.5.2: - version "0.5.2" - resolved "https://registry.npmjs.org/react-motion/-/react-motion-0.5.2.tgz#0dd3a69e411316567927917c6626551ba0607316" - integrity sha512-9q3YAvHoUiWlP3cK0v+w1N5Z23HXMj4IF4YuvjvWegWqNPfLXsOBE/V7UvQGpXxHFKRQQcNcVQE31g9SB/6qgQ== - dependencies: - performance-now "^0.2.0" - prop-types "^15.5.8" - raf "^3.1.0" - react-popper-tooltip@^3.1.1: version "3.1.1" resolved "https://registry.npmjs.org/react-popper-tooltip/-/react-popper-tooltip-3.1.1.tgz#329569eb7b287008f04fcbddb6370452ad3f9eac" @@ -23098,28 +23043,17 @@ react-popper@^2.2.4: react-fast-compare "^3.0.1" warning "^4.0.2" -react-redux@=4.4.10: - version "4.4.10" - resolved "https://registry.npmjs.org/react-redux/-/react-redux-4.4.10.tgz#ad57bd1db00c2d0aa7db992b360ce63dd0b80ec5" - integrity sha512-tjL0Bmpkj75Td0k+lXlF8Fc8a9GuXFv/3ahUOCXExWs/jhsKiQeTffdH0j5byejCGCRL4tvGFYlrwBF1X/Aujg== +react-redux@^7.1.1, react-redux@^7.2.4: + version "7.2.5" + resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.5.tgz#213c1b05aa1187d9c940ddfc0b29450957f6a3b8" + integrity sha512-Dt29bNyBsbQaysp6s/dN0gUodcq+dVKKER8Qv82UrpeygwYeX1raTtil7O/fftw/rFqzaf6gJhDZRkkZnn6bjg== dependencies: - create-react-class "^15.5.1" - hoist-non-react-statics "^3.3.0" - invariant "^2.0.0" - lodash "^4.17.11" + "@babel/runtime" "^7.12.1" + "@types/react-redux" "^7.1.16" + hoist-non-react-statics "^3.3.2" loose-envify "^1.4.0" prop-types "^15.7.2" - -react-redux@^7.1.1: - version "7.2.0" - resolved "https://registry.npmjs.org/react-redux/-/react-redux-7.2.0.tgz#f970f62192b3981642fec46fd0db18a074fe879d" - integrity sha512-EvCAZYGfOLqwV7gh849xy9/pt55rJXPwmYvI4lilPM5rUT/1NxuuN59ipdBksRVSvz0KInbPnp4IfoXJXCqiDA== - dependencies: - "@babel/runtime" "^7.5.5" - hoist-non-react-statics "^3.3.0" - loose-envify "^1.4.0" - prop-types "^15.7.2" - react-is "^16.9.0" + react-is "^16.13.1" react-refresh@^0.8.3: version "0.8.3" @@ -23201,7 +23135,7 @@ react-syntax-highlighter@^13.5.3: prismjs "^1.21.0" refractor "^3.1.0" -react-syntax-highlighter@^15.4.3: +react-syntax-highlighter@^15.4.3, react-syntax-highlighter@^15.4.4: version "15.4.4" resolved "https://registry.npmjs.org/react-syntax-highlighter/-/react-syntax-highlighter-15.4.4.tgz#dc9043f19e7bd063ff3ea78986d22a6eaa943b2a" integrity sha512-PsOFHNTzkb3OroXdoR897eKN5EZ6grht1iM+f1lJSq7/L0YVnkJaNVwC3wEUYPOAmeyl5xyer1DjL6MrumO6Zw== @@ -23614,22 +23548,17 @@ reduce-function-call@^1.0.1: dependencies: balanced-match "^1.0.0" -redux-immutable@3.1.0: - version "3.1.0" - resolved "https://registry.npmjs.org/redux-immutable/-/redux-immutable-3.1.0.tgz#cafbd686e0711261119b9c28960935dc47a49d0a" - integrity sha1-yvvWhuBxEmERm5wolgk13EeknQo= - dependencies: - immutable "^3.8.1" +redux-immutable@^4.0.0: + version "4.0.0" + resolved "https://registry.npmjs.org/redux-immutable/-/redux-immutable-4.0.0.tgz#3a1a32df66366462b63691f0e1dc35e472bbc9f3" + integrity sha1-Ohoy32Y2ZGK2NpHw4dw15HK7yfM= -redux@=3.7.2: - version "3.7.2" - resolved "https://registry.npmjs.org/redux/-/redux-3.7.2.tgz#06b73123215901d25d065be342eb026bc1c8537b" - integrity sha512-pNqnf9q1hI5HHZRBkj3bAngGZW/JMCmexDlOxw4XagXY2o1327nHH54LoTjiPJ0gizoqPDRqWyX/00g0hD6w+A== +redux@^4.0.0, redux@^4.1.0: + version "4.1.1" + resolved "https://registry.npmjs.org/redux/-/redux-4.1.1.tgz#76f1c439bb42043f985fbd9bf21990e60bd67f47" + integrity sha512-hZQZdDEM25UY2P493kPYuKqviVwZ58lEmGQNeQ+gXa+U0gYPUBf7NKYazbe3m+bs/DzM/ahN12DbF+NG8i0CWw== dependencies: - lodash "^4.2.1" - lodash-es "^4.2.1" - loose-envify "^1.1.0" - symbol-observable "^1.0.3" + "@babel/runtime" "^7.9.2" redux@^4.0.4: version "4.0.5" @@ -25435,13 +25364,6 @@ stream-transform@^2.0.1: dependencies: mixme "^0.3.1" -stream@^0.0.2: - version "0.0.2" - resolved "https://registry.npmjs.org/stream/-/stream-0.0.2.tgz#7f5363f057f6592c5595f00bc80a27f5cec1f0ef" - integrity sha1-f1Nj8Ff2WSxVlfALyAon9c7B8O8= - dependencies: - emitter-component "^1.1.1" - streamsearch@0.1.2, streamsearch@~0.1.2: version "0.1.2" resolved "https://registry.npmjs.org/streamsearch/-/streamsearch-0.1.2.tgz#808b9d0e56fc273d809ba57338e929919a1a9f1a" @@ -25898,10 +25820,10 @@ svgo@^1.0.0, svgo@^1.2.2: unquote "~1.1.1" util.promisify "~1.0.0" -swagger-client@^3.15.0: - version "3.15.0" - resolved "https://registry.npmjs.org/swagger-client/-/swagger-client-3.15.0.tgz#ba9de5830a8baf40ec5a867e815fa4588d974fa3" - integrity sha512-8Ki4bVbT+bl8hGmy3vR89wktZhVLXKNUk8CoUvfwn7Rq45bZ15c9UQXVr4VU6hP3f9diWJGJs0bKZR9pPOq4ZA== +swagger-client@^3.16.1: + version "3.16.1" + resolved "https://registry.npmjs.org/swagger-client/-/swagger-client-3.16.1.tgz#df86c9d407ab52c00cb356e714b0ec732bb3ad40" + integrity sha512-BcNRQzXHRGuXfhN0f80ptlr+bSaPvXwo8+gWbpmTnbKdAjcWOKAWwUx7rgGHjTKZh0qROr/GX9xOZIY8LrBuTg== dependencies: "@babel/runtime-corejs3" "^7.11.2" btoa "^1.2.1" @@ -25910,24 +25832,22 @@ swagger-client@^3.15.0: cross-fetch "^3.1.4" deep-extend "~0.6.0" fast-json-patch "^3.0.0-1" - form-data-encoder "^1.0.1" - formdata-node "^3.6.2" + form-data-encoder "^1.4.3" + formdata-node "^4.0.0" js-yaml "^4.1.0" - lodash "^4.17.19" + lodash "^4.17.21" qs "^6.9.4" querystring-browser "^1.0.4" traverse "~0.6.6" url "~0.11.0" -swagger-ui-react@^3.37.2: - version "3.52.0" - resolved "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-3.52.0.tgz#edf85fed58d55677fc49807ff7d67e43e2d5bf44" - integrity sha512-JBw2Omif7i8pFIW8PHsoHZDXhn1LhiPmzxl6NRYGaoCxKDi+HQAQthvZ3piJbDQ8vS3EjtlVh7lkBn/RtrkPww== +swagger-ui-react@^4.0.0-rc.3: + version "4.0.0-rc.3" + resolved "https://registry.npmjs.org/swagger-ui-react/-/swagger-ui-react-4.0.0-rc.3.tgz#393f424daf55272dd36737be654d978daf870d3d" + integrity sha512-Mo3+NvwLbbPy+ZJZoQkc3UudevSM03SHTZqwZOI7EY4KyMgqeet3xElnAUGZC94GqBZTstU0rf/znkgdaNo9qg== dependencies: "@babel/runtime-corejs3" "^7.14.7" "@braintree/sanitize-url" "^5.0.2" - "@kyleshockey/object-assign-deep" "^0.4.2" - "@kyleshockey/xml" "^1.0.2" base64-js "^1.5.1" classnames "^2.3.1" css.escape "1.5.1" @@ -25942,21 +25862,21 @@ swagger-ui-react@^3.37.2: prop-types "^15.7.2" randombytes "^2.1.0" react-copy-to-clipboard "5.0.3" - react-debounce-input "^3.2.3" + react-debounce-input "=3.2.4" react-immutable-proptypes "2.2.0" - react-immutable-pure-component "^1.1.1" - react-inspector "^2.3.0" - react-motion "^0.5.2" - react-redux "=4.4.10" - react-syntax-highlighter "^15.4.3" - redux "=3.7.2" - redux-immutable "3.1.0" + react-immutable-pure-component "^2.2.0" + react-inspector "^5.1.1" + react-redux "^7.2.4" + react-syntax-highlighter "^15.4.4" + redux "^4.1.0" + redux-immutable "^4.0.0" remarkable "^2.0.1" reselect "^4.0.0" serialize-error "^8.1.0" sha.js "^2.4.11" - swagger-client "^3.15.0" - url-parse "^1.5.1" + swagger-client "^3.16.1" + url-parse "^1.5.3" + xml "=1.0.1" xml-but-prettier "^1.0.1" zenscroll "^4.0.2" @@ -25967,7 +25887,7 @@ swap-case@^2.0.2: dependencies: tslib "^2.0.3" -symbol-observable@1.2.0, symbol-observable@^1.0.3, symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0: +symbol-observable@1.2.0, symbol-observable@^1.0.4, symbol-observable@^1.1.0, symbol-observable@^1.2.0: version "1.2.0" resolved "https://registry.npmjs.org/symbol-observable/-/symbol-observable-1.2.0.tgz#c22688aed4eab3cdc2dfeacbb561660560a00804" integrity sha512-e900nM8RRtGhlV36KGEU9k65K3mPb1WV70OdjfxlG2EAuM1noi/E/BaW/uMhL7bPEssK8QV57vN3esixjUvcXQ== @@ -27257,7 +27177,7 @@ url-parse-lax@^3.0.0: dependencies: prepend-http "^2.0.0" -url-parse@^1.4.3, url-parse@^1.5.1: +url-parse@^1.4.3, url-parse@^1.5.3: version "1.5.3" resolved "https://registry.npmjs.org/url-parse/-/url-parse-1.5.3.tgz#71c1303d38fb6639ade183c2992c8cc0686df862" integrity sha512-IIORyIQD9rvj0A4CLWsHkBBJuNqWpFQe224b6j9t/ABmquIS0qDU2pY6kl6AuOrL5OkCXHMCFNe1jBcuAggjvQ== @@ -27669,6 +27589,11 @@ web-namespaces@^1.0.0: resolved "https://registry.npmjs.org/web-namespaces/-/web-namespaces-1.1.4.tgz#bc98a3de60dadd7faefc403d1076d529f5e030ec" integrity sha512-wYxSGajtmoP4WxfejAPIr4l0fVh+jeMXZb08wNc0tMg6xsfZXj3cECqIK0G7ZAqUq0PP8WlMDtaOGVBTAWztNw== +web-streams-polyfill@4.0.0-beta.1: + version "4.0.0-beta.1" + resolved "https://registry.npmjs.org/web-streams-polyfill/-/web-streams-polyfill-4.0.0-beta.1.tgz#3b19b9817374b7cee06d374ba7eeb3aeb80e8c95" + integrity sha512-3ux37gEX670UUphBF9AMCq8XM6iQ8Ac6A+DSRRjDoRBm1ufCkaCDdNVbaqq60PsEkdNlLKrGtv/YBP4EJXqNtQ== + webidl-conversions@^4.0.2: version "4.0.2" resolved "https://registry.npmjs.org/webidl-conversions/-/webidl-conversions-4.0.2.tgz#a855980b1f0b6b359ba1d5d9fb39ae941faa63ad" @@ -28235,6 +28160,11 @@ xml2js@^0.4.11, xml2js@^0.4.19, xml2js@^0.4.23: sax ">=0.6.0" xmlbuilder "~11.0.0" +xml@=1.0.1: + version "1.0.1" + resolved "https://registry.npmjs.org/xml/-/xml-1.0.1.tgz#78ba72020029c5bc87b8a81a3cfcd74b4a2fc1e5" + integrity sha1-eLpyAgApxbyHuKgaPPzXS0ovweU= + xmlbuilder@^15.1.1: version "15.1.1" resolved "https://registry.npmjs.org/xmlbuilder/-/xmlbuilder-15.1.1.tgz#9dcdce49eea66d8d10b42cae94a79c3c8d0c2ec5"