diff --git a/.changeset/big-dancers-deliver.md b/.changeset/big-dancers-deliver.md new file mode 100644 index 0000000000..729f3109a8 --- /dev/null +++ b/.changeset/big-dancers-deliver.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-apache-airflow': patch +--- + +added an optional ESLint rule - no-top-level-material-ui-4-imports - which has an auto fix function to migrate the imports and used it to migrate the imports for plugins/apache-airflow diff --git a/.changeset/clever-pumpkins-brush.md b/.changeset/clever-pumpkins-brush.md new file mode 100644 index 0000000000..a609e874cd --- /dev/null +++ b/.changeset/clever-pumpkins-brush.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-api-docs': patch +--- + +added an optional ESLint rule - no-top-level-material-ui-4-imports - in api-docs plugin which has an auto fix function to migrate the imports and used it to migrate the material-ui imports for plugins/api-docs diff --git a/.changeset/cli-pack-so-exhausting.md b/.changeset/cli-pack-so-exhausting.md new file mode 100644 index 0000000000..e4f92521d0 --- /dev/null +++ b/.changeset/cli-pack-so-exhausting.md @@ -0,0 +1,5 @@ +--- +'@backstage/cli': patch +--- + +Fixed a bug that could cause the `build-workspace` command to fail when invoked with `--alwaysYarnPack` enabled in environments with limited resources. diff --git a/.changeset/curvy-tigers-cross.md b/.changeset/curvy-tigers-cross.md new file mode 100644 index 0000000000..1a55960f89 --- /dev/null +++ b/.changeset/curvy-tigers-cross.md @@ -0,0 +1,6 @@ +--- +'@backstage/plugin-notifications-backend': patch +'@backstage/plugin-notifications': patch +--- + +All notifications can be marked and filtered by severity critical, high, normal or low, the default is 'normal' diff --git a/.changeset/fluffy-rocks-confess.md b/.changeset/fluffy-rocks-confess.md new file mode 100644 index 0000000000..892ec39ad7 --- /dev/null +++ b/.changeset/fluffy-rocks-confess.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-explore': patch +--- + +Added an optional ESLint rule - no-top-level-material-ui-4-imports -in explore plugin which has an auto fix function to migrate the imports and used it to migrate the Material UI imports for plugins/explore. diff --git a/.changeset/fresh-worms-build.md b/.changeset/fresh-worms-build.md new file mode 100644 index 0000000000..a2518e46cb --- /dev/null +++ b/.changeset/fresh-worms-build.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-catalog': patch +--- + +Resolved an issue where the `PaginatedCatalogTable` was not propagating table options to its child table. diff --git a/.changeset/fuzzy-weeks-press.md b/.changeset/fuzzy-weeks-press.md new file mode 100644 index 0000000000..8d65436de3 --- /dev/null +++ b/.changeset/fuzzy-weeks-press.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-circleci': patch +--- + +Added an optional ESLint rule - no-top-level-material-ui-4-imports - in CircleCI plugin which has an auto fix function to migrate the imports and used it to migrate the Material UI imports for `plugins/circleci`. diff --git a/.changeset/hot-moles-lay.md b/.changeset/hot-moles-lay.md index 90adcbd07b..69a763ac16 100644 --- a/.changeset/hot-moles-lay.md +++ b/.changeset/hot-moles-lay.md @@ -2,4 +2,4 @@ '@backstage/plugin-airbrake': patch --- -added an optional ESLint rule - no-top-level-material-ui-4-imports - which has an auto fix function to migrate the imports and using it migrated the imports +Added an optional ESLint rule - no-top-level-material-ui-4-imports - which has an auto fix function to migrate the imports and using it migrated the imports. diff --git a/.changeset/loud-llamas-call.md b/.changeset/loud-llamas-call.md new file mode 100644 index 0000000000..c4c05a8147 --- /dev/null +++ b/.changeset/loud-llamas-call.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-cloudbuild': patch +--- + +Added an optional ESLint rule - no-top-level-material-ui-4-imports -in cloudbuild plugin which has an auto fix function to migrate the imports and used it to migrate the Material UI imports for plugins/cloudbuild. diff --git a/.changeset/mighty-fishes-wait.md b/.changeset/mighty-fishes-wait.md new file mode 100644 index 0000000000..d896a83665 --- /dev/null +++ b/.changeset/mighty-fishes-wait.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-apollo-explorer': patch +--- + +Added an optional ESLint rule - no-top-level-material-ui-4-imports -in apollo-explorer plugin which has an auto fix function to migrate the imports and used it to migrate the Material UI imports for plugins/apollo-explorer. diff --git a/.changeset/neat-rivers-happen.md b/.changeset/neat-rivers-happen.md new file mode 100644 index 0000000000..1c35a9949d --- /dev/null +++ b/.changeset/neat-rivers-happen.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-bazaar': patch +--- + +Added an optional ESLint rule - no-top-level-material-ui-4-imports - in bazaar plugin which has an auto fix function to migrate the imports and used it to migrate the Material UI imports for plugins/bazaar diff --git a/.changeset/pink-zoos-own.md b/.changeset/pink-zoos-own.md new file mode 100644 index 0000000000..9a38855300 --- /dev/null +++ b/.changeset/pink-zoos-own.md @@ -0,0 +1,5 @@ +--- +'@backstage/plugin-kubernetes': patch +--- + +Added an optional ESLint rule - no-top-level-material-ui-4-imports -in kubernetes plugin which has an auto fix function to migrate the imports and used it to migrate the Material UI imports for plugins/kubernetes. diff --git a/.github/workflows/sync_snyk-github-issues.yml b/.github/workflows/sync_snyk-github-issues.yml index 02d4d55301..638f5213be 100644 --- a/.github/workflows/sync_snyk-github-issues.yml +++ b/.github/workflows/sync_snyk-github-issues.yml @@ -29,7 +29,7 @@ jobs: cache-prefix: ${{ runner.os }}-v18.x - name: Create Snyk report - uses: snyk/actions/node@1d672a455ab3339ef0a0021e1ec809165ee12fad # master + uses: snyk/actions/node@8349f9043a8b7f0f3ee8885bf28f0b388d2446e8 # master continue-on-error: true # Snyk CLI exits with error when vulnerabilities are found with: args: > diff --git a/.github/workflows/sync_snyk-monitor.yml b/.github/workflows/sync_snyk-monitor.yml index c5374951d7..1ffc8d2c26 100644 --- a/.github/workflows/sync_snyk-monitor.yml +++ b/.github/workflows/sync_snyk-monitor.yml @@ -31,7 +31,7 @@ jobs: - uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4.1.1 - name: Monitor and Synchronize Snyk Policies - uses: snyk/actions/node@1d672a455ab3339ef0a0021e1ec809165ee12fad # master + uses: snyk/actions/node@8349f9043a8b7f0f3ee8885bf28f0b388d2446e8 # master with: command: monitor args: > @@ -46,7 +46,7 @@ jobs: # Above we run the `monitor` command, this runs the `test` command which is # the one that generates the SARIF report that we can upload to GitHub. - name: Create Snyk report - uses: snyk/actions/node@1d672a455ab3339ef0a0021e1ec809165ee12fad # master + uses: snyk/actions/node@8349f9043a8b7f0f3ee8885bf28f0b388d2446e8 # master continue-on-error: true # To make sure that SARIF upload gets called with: args: > diff --git a/packages/cli/package.json b/packages/cli/package.json index 910769ff06..163c204ec7 100644 --- a/packages/cli/package.json +++ b/packages/cli/package.json @@ -112,6 +112,7 @@ "node-libs-browser": "^2.2.1", "npm-packlist": "^5.0.0", "ora": "^5.3.0", + "p-limit": "^3.1.0", "p-queue": "^6.6.2", "postcss": "^8.1.0", "process": "^0.11.10", diff --git a/packages/cli/src/lib/packager/createDistWorkspace.ts b/packages/cli/src/lib/packager/createDistWorkspace.ts index 00b8784d6d..9cb54f2830 100644 --- a/packages/cli/src/lib/packager/createDistWorkspace.ts +++ b/packages/cli/src/lib/packager/createDistWorkspace.ts @@ -21,6 +21,7 @@ import { resolve as resolvePath, relative as relativePath, } from 'path'; +import pLimit from 'p-limit'; import { tmpdir } from 'os'; import tar, { CreateOptions, FileOptions } from 'tar'; import partition from 'lodash/partition'; @@ -352,9 +353,11 @@ async function moveToDistWorkspace( } // Repacking in parallel is much faster and safe for all packages outside of the Backstage repo + // Limit concurrency to 10 to avoid resource exhaustion on larger monorepos. + const limit = pLimit(10); await Promise.all( - safePackages.map(async (target, index) => - pack(target, `temp-package-${index}.tgz`), + safePackages.map((target, index) => + limit(() => pack(target, `temp-package-${index}.tgz`)), ), ); } diff --git a/plugins/apache-airflow/.eslintrc.js b/plugins/apache-airflow/.eslintrc.js index e2a53a6ad2..9d5b45a010 100644 --- a/plugins/apache-airflow/.eslintrc.js +++ b/plugins/apache-airflow/.eslintrc.js @@ -1 +1,5 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); \ No newline at end of file diff --git a/plugins/apache-airflow/src/components/HomePage/HomePage.tsx b/plugins/apache-airflow/src/components/HomePage/HomePage.tsx index 442f1bf4a0..9e988df198 100644 --- a/plugins/apache-airflow/src/components/HomePage/HomePage.tsx +++ b/plugins/apache-airflow/src/components/HomePage/HomePage.tsx @@ -22,7 +22,7 @@ import { Page, SupportButton, } from '@backstage/core-components'; -import { Grid } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; import React from 'react'; import { DagTableComponent } from '../DagTableComponent'; import { StatusComponent } from '../StatusComponent'; diff --git a/plugins/apache-airflow/src/components/LatestDagRunsStatus/LatestDagRunsStatus.tsx b/plugins/apache-airflow/src/components/LatestDagRunsStatus/LatestDagRunsStatus.tsx index 90cb0694f8..d243f48e8a 100644 --- a/plugins/apache-airflow/src/components/LatestDagRunsStatus/LatestDagRunsStatus.tsx +++ b/plugins/apache-airflow/src/components/LatestDagRunsStatus/LatestDagRunsStatus.tsx @@ -18,17 +18,15 @@ import { apacheAirflowApiRef } from '../../api'; import useAsync from 'react-use/lib/useAsync'; import { DagRun } from '../../api/types/Dags'; import { useApi } from '@backstage/core-plugin-api'; -import { - Box, - Button, - CircularProgress, - List, - ListItem, - ListItemIcon, - makeStyles, - Tooltip, - Typography, -} from '@material-ui/core'; +import Box from '@material-ui/core/Box'; +import Button from '@material-ui/core/Button'; +import CircularProgress from '@material-ui/core/CircularProgress'; +import List from '@material-ui/core/List'; +import ListItem from '@material-ui/core/ListItem'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import Tooltip from '@material-ui/core/Tooltip'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; import { Link, StatusError, diff --git a/plugins/api-docs/.eslintrc.js b/plugins/api-docs/.eslintrc.js index e2a53a6ad2..9d5b45a010 100644 --- a/plugins/api-docs/.eslintrc.js +++ b/plugins/api-docs/.eslintrc.js @@ -1 +1,5 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); \ No newline at end of file diff --git a/plugins/api-docs/src/alpha.tsx b/plugins/api-docs/src/alpha.tsx index 8cb43e9108..48dae28cdd 100644 --- a/plugins/api-docs/src/alpha.tsx +++ b/plugins/api-docs/src/alpha.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; -import { Grid } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; import { createApiExtension, diff --git a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx index 679069f209..30bd7623fe 100644 --- a/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionCard/ApiDefinitionCard.tsx @@ -16,7 +16,7 @@ import { ApiEntity } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; -import { Alert } from '@material-ui/lab'; +import Alert from '@material-ui/lab/Alert'; import React from 'react'; import { apiDocsConfigRef } from '../../config'; import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget'; diff --git a/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx b/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx index 6673420732..7e532e0049 100644 --- a/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx +++ b/plugins/api-docs/src/components/ApiDefinitionDialog/ApiDefinitionDialog.tsx @@ -16,18 +16,16 @@ import { ApiEntity } from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; -import { - Box, - Button, - Dialog, - DialogActions, - DialogContent, - DialogTitle, - makeStyles, - Tab, - Tabs, - Typography, -} from '@material-ui/core'; +import Box from '@material-ui/core/Box'; +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 Tab from '@material-ui/core/Tab'; +import Tabs from '@material-ui/core/Tabs'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; import React, { useEffect } from 'react'; import { apiDocsConfigRef } from '../../config'; import { PlainApiDefinitionWidget } from '../PlainApiDefinitionWidget'; diff --git a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx index f56bd3e1a7..d5494d1818 100644 --- a/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx +++ b/plugins/api-docs/src/components/ApisCards/ConsumedApisCard.tsx @@ -15,7 +15,7 @@ */ import { ApiEntity, RELATION_CONSUMES_API } from '@backstage/catalog-model'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; import { EntityTable, useEntity, diff --git a/plugins/api-docs/src/components/ApisCards/HasApisCard.tsx b/plugins/api-docs/src/components/ApisCards/HasApisCard.tsx index b8aef1bca4..d58a654176 100644 --- a/plugins/api-docs/src/components/ApisCards/HasApisCard.tsx +++ b/plugins/api-docs/src/components/ApisCards/HasApisCard.tsx @@ -15,7 +15,7 @@ */ import { ApiEntity, RELATION_HAS_PART } from '@backstage/catalog-model'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; import { EntityTable, useEntity, diff --git a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx index 886ba17ba5..97d0a00b0a 100644 --- a/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx +++ b/plugins/api-docs/src/components/ApisCards/ProvidedApisCard.tsx @@ -15,7 +15,7 @@ */ import { ApiEntity, RELATION_PROVIDES_API } from '@backstage/catalog-model'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; import { EntityTable, useEntity, diff --git a/plugins/api-docs/src/components/ApisCards/presets.tsx b/plugins/api-docs/src/components/ApisCards/presets.tsx index 050944b239..b3543b79f5 100644 --- a/plugins/api-docs/src/components/ApisCards/presets.tsx +++ b/plugins/api-docs/src/components/ApisCards/presets.tsx @@ -18,7 +18,7 @@ import { ApiEntity } from '@backstage/catalog-model'; import { TableColumn } from '@backstage/core-components'; import { EntityTable } from '@backstage/plugin-catalog-react'; import ExtensionIcon from '@material-ui/icons/Extension'; -import { ToggleButton } from '@material-ui/lab'; +import ToggleButton from '@material-ui/lab/ToggleButton'; import React, { useState } from 'react'; import { ApiTypeTitle } from '../ApiDefinitionCard'; import { ApiDefinitionDialog } from '../ApiDefinitionDialog'; diff --git a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.tsx b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.tsx index 461e466b4f..85ce15132a 100644 --- a/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.tsx +++ b/plugins/api-docs/src/components/AsyncApiDefinitionWidget/AsyncApiDefinition.tsx @@ -18,7 +18,7 @@ import AsyncApi from '@asyncapi/react-component'; import '@asyncapi/react-component/styles/default.css'; import { makeStyles, alpha, darken } from '@material-ui/core/styles'; import React from 'react'; -import { useTheme } from '@material-ui/core'; +import { useTheme } from '@material-ui/core/styles'; const useStyles = makeStyles(theme => ({ root: { diff --git a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx index aa6afc7822..5feb1c96e4 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ConsumingComponentsCard.tsx @@ -18,7 +18,7 @@ import { ComponentEntity, RELATION_API_CONSUMED_BY, } from '@backstage/catalog-model'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; import { EntityTable, useEntity, diff --git a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx index 435021e008..ef7f2e1071 100644 --- a/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx +++ b/plugins/api-docs/src/components/ComponentsCards/ProvidingComponentsCard.tsx @@ -18,7 +18,7 @@ import { ComponentEntity, RELATION_API_PROVIDED_BY, } from '@backstage/catalog-model'; -import { Typography } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; import { EntityTable, useEntity, diff --git a/plugins/apollo-explorer/.eslintrc.js b/plugins/apollo-explorer/.eslintrc.js index e2a53a6ad2..9d5b45a010 100644 --- a/plugins/apollo-explorer/.eslintrc.js +++ b/plugins/apollo-explorer/.eslintrc.js @@ -1 +1,5 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); \ No newline at end of file diff --git a/plugins/apollo-explorer/src/components/ApolloExplorerBrowser/ApolloExplorerBrowser.tsx b/plugins/apollo-explorer/src/components/ApolloExplorerBrowser/ApolloExplorerBrowser.tsx index 57f9eb7f8a..cf7ef16339 100644 --- a/plugins/apollo-explorer/src/components/ApolloExplorerBrowser/ApolloExplorerBrowser.tsx +++ b/plugins/apollo-explorer/src/components/ApolloExplorerBrowser/ApolloExplorerBrowser.tsx @@ -15,7 +15,10 @@ */ import React, { useState } from 'react'; -import { Divider, makeStyles, Tab, Tabs } from '@material-ui/core'; +import Divider from '@material-ui/core/Divider'; +import Tab from '@material-ui/core/Tab'; +import Tabs from '@material-ui/core/Tabs'; +import { makeStyles } from '@material-ui/core/styles'; import { JSONObject } from '@apollo/explorer/src/helpers/types'; import { ApolloExplorer } from '@apollo/explorer/react'; import { Content } from '@backstage/core-components'; diff --git a/plugins/bazaar/.eslintrc.js b/plugins/bazaar/.eslintrc.js index e2a53a6ad2..9d5b45a010 100644 --- a/plugins/bazaar/.eslintrc.js +++ b/plugins/bazaar/.eslintrc.js @@ -1 +1,5 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); \ No newline at end of file diff --git a/plugins/bazaar/src/components/About/About.tsx b/plugins/bazaar/src/components/About/About.tsx index 68525ab642..c94a149de9 100644 --- a/plugins/bazaar/src/components/About/About.tsx +++ b/plugins/bazaar/src/components/About/About.tsx @@ -15,7 +15,9 @@ */ import React from 'react'; -import { Grid, Typography, makeStyles } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; import { InfoCard, Link } from '@backstage/core-components'; const useStyles = makeStyles({ diff --git a/plugins/bazaar/src/components/BazaarOverviewCard/BazaarOverviewCard.tsx b/plugins/bazaar/src/components/BazaarOverviewCard/BazaarOverviewCard.tsx index da43d4a206..3dc5521275 100644 --- a/plugins/bazaar/src/components/BazaarOverviewCard/BazaarOverviewCard.tsx +++ b/plugins/bazaar/src/components/BazaarOverviewCard/BazaarOverviewCard.tsx @@ -26,7 +26,7 @@ import { fetchCatalogItems } from '../../util/fetchMethods'; import { parseBazaarProject } from '../../util/parseMethods'; import { ErrorPanel, InfoCard, Link } from '@backstage/core-components'; import { bazaarPlugin } from '../../plugin'; -import { IconButton } from '@material-ui/core'; +import IconButton from '@material-ui/core/IconButton'; import StorefrontIcon from '@material-ui/icons/Storefront'; /** @public */ diff --git a/plugins/bazaar/src/components/CardContentFields/AboutField.tsx b/plugins/bazaar/src/components/CardContentFields/AboutField.tsx index e8c49bf4d7..8efb901682 100644 --- a/plugins/bazaar/src/components/CardContentFields/AboutField.tsx +++ b/plugins/bazaar/src/components/CardContentFields/AboutField.tsx @@ -15,7 +15,9 @@ */ import { useElementFilter } from '@backstage/core-plugin-api'; -import { Grid, makeStyles, Typography } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; import React from 'react'; const useStyles = makeStyles(theme => ({ diff --git a/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx b/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx index f252efebee..247a1f6011 100644 --- a/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx +++ b/plugins/bazaar/src/components/CardContentFields/CardContentFields.tsx @@ -15,13 +15,11 @@ */ import React from 'react'; -import { - Grid, - Card, - CardContent, - Typography, - GridSize, -} from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; +import Card from '@material-ui/core/Card'; +import CardContent from '@material-ui/core/CardContent'; +import Typography from '@material-ui/core/Typography'; +import { GridSize } from '@material-ui/core/Grid'; import { parseEntityRef } from '@backstage/catalog-model'; import { Avatar, Link } from '@backstage/core-components'; import { useRouteRef } from '@backstage/core-plugin-api'; diff --git a/plugins/bazaar/src/components/DateSelector/DateSelector.tsx b/plugins/bazaar/src/components/DateSelector/DateSelector.tsx index 600247a53f..0fbafe30e5 100644 --- a/plugins/bazaar/src/components/DateSelector/DateSelector.tsx +++ b/plugins/bazaar/src/components/DateSelector/DateSelector.tsx @@ -18,12 +18,10 @@ import React from 'react'; import FormControl from '@material-ui/core/FormControl'; import { Controller, Control, UseFormSetValue } from 'react-hook-form'; import { FormValues } from '../../types'; -import { - KeyboardDatePicker, - MuiPickersUtilsProvider, -} from '@material-ui/pickers'; +import { KeyboardDatePicker } from '@material-ui/pickers/DatePicker'; +import MuiPickersUtilsProvider from '@material-ui/pickers/MuiPickersUtilsProvider'; import LuxonUtils from '@date-io/luxon'; -import { IconButton } from '@material-ui/core'; +import IconButton from '@material-ui/core/IconButton'; import ClearIcon from '@material-ui/icons/Clear'; type Props = { diff --git a/plugins/bazaar/src/components/DoubleDateSelector/DoubleDateSelector.tsx b/plugins/bazaar/src/components/DoubleDateSelector/DoubleDateSelector.tsx index eb72ee67dc..7cd208cd3f 100644 --- a/plugins/bazaar/src/components/DoubleDateSelector/DoubleDateSelector.tsx +++ b/plugins/bazaar/src/components/DoubleDateSelector/DoubleDateSelector.tsx @@ -18,7 +18,8 @@ import React from 'react'; import { Control, UseFormSetValue } from 'react-hook-form'; import { FormValues } from '../../types'; import { DateSelector } from '../DateSelector/DateSelector'; -import { Typography, makeStyles } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; type Props = { control: Control; diff --git a/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx b/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx index 2c5539b988..01c36a8d72 100644 --- a/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx +++ b/plugins/bazaar/src/components/EditProjectDialog/EditProjectDialog.tsx @@ -21,7 +21,8 @@ import { BazaarProject, FormValues } from '../../types'; import { bazaarApiRef } from '../../api'; import { UseFormGetValues } from 'react-hook-form'; import { ConfirmationDialog } from '../ConfirmationDialog'; -import { Button, makeStyles } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import { makeStyles } from '@material-ui/core/styles'; type Props = { bazaarProject: BazaarProject; diff --git a/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx b/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx index ba38f3189e..c89e2ec34e 100644 --- a/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx +++ b/plugins/bazaar/src/components/EntityBazaarInfoCard/EntityBazaarInfoCard.tsx @@ -21,7 +21,7 @@ import { stringifyEntityRef } from '@backstage/catalog-model'; import { useEntity } from '@backstage/plugin-catalog-react'; import { bazaarApiRef } from '../../api'; import { EntityBazaarInfoContent } from '../EntityBazaarInfoContent'; -import { Card } from '@material-ui/core'; +import Card from '@material-ui/core/Card'; import { parseBazaarResponse } from '../../util/parseMethods'; /** @public */ diff --git a/plugins/bazaar/src/components/EntityBazaarInfoContent/EntityBazaarInfoContent.tsx b/plugins/bazaar/src/components/EntityBazaarInfoContent/EntityBazaarInfoContent.tsx index 0c7b0bb126..250a4a489d 100644 --- a/plugins/bazaar/src/components/EntityBazaarInfoContent/EntityBazaarInfoContent.tsx +++ b/plugins/bazaar/src/components/EntityBazaarInfoContent/EntityBazaarInfoContent.tsx @@ -15,7 +15,10 @@ */ import React, { useState, useEffect } from 'react'; -import { CardHeader, Divider, IconButton, makeStyles } from '@material-ui/core'; +import CardHeader from '@material-ui/core/CardHeader'; +import Divider from '@material-ui/core/Divider'; +import IconButton from '@material-ui/core/IconButton'; +import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import { HeaderIconLinkRow, @@ -31,7 +34,7 @@ import { EditProjectDialog } from '../EditProjectDialog'; import { useApi, identityApiRef } from '@backstage/core-plugin-api'; import { BazaarProject, Member } from '../../types'; import { bazaarApiRef } from '../../api'; -import { Alert } from '@material-ui/lab'; +import Alert from '@material-ui/lab/Alert'; import useAsyncFn from 'react-use/lib/useAsyncFn'; import ExitToAppIcon from '@material-ui/icons/ExitToApp'; import { parseEntityRef } from '@backstage/catalog-model'; diff --git a/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx b/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx index c361098273..e522b6b8c4 100644 --- a/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx +++ b/plugins/bazaar/src/components/HomePageBazaarInfoCard/HomePageBazaarInfoCard.tsx @@ -15,13 +15,11 @@ */ import React, { useState, useEffect } from 'react'; -import { - Card, - CardHeader, - Divider, - IconButton, - makeStyles, -} from '@material-ui/core'; +import Card from '@material-ui/core/Card'; +import CardHeader from '@material-ui/core/CardHeader'; +import Divider from '@material-ui/core/Divider'; +import IconButton from '@material-ui/core/IconButton'; +import { makeStyles } from '@material-ui/core/styles'; import Typography from '@material-ui/core/Typography'; import { HeaderIconLinkRow, @@ -45,7 +43,7 @@ import { } from '@backstage/core-plugin-api'; import { Member, BazaarProject } from '../../types'; import { bazaarApiRef } from '../../api'; -import { Alert } from '@material-ui/lab'; +import Alert from '@material-ui/lab/Alert'; import useAsyncFn from 'react-use/lib/useAsyncFn'; import { catalogApiRef, entityRouteRef } from '@backstage/plugin-catalog-react'; diff --git a/plugins/bazaar/src/components/InputField/InputField.tsx b/plugins/bazaar/src/components/InputField/InputField.tsx index a926ac41ad..bd6cbfce51 100644 --- a/plugins/bazaar/src/components/InputField/InputField.tsx +++ b/plugins/bazaar/src/components/InputField/InputField.tsx @@ -21,7 +21,7 @@ import { FieldError, ValidationRule, } from 'react-hook-form'; -import { TextField } from '@material-ui/core'; +import TextField from '@material-ui/core/TextField'; import { FormValues } from '../../types'; type Rules = { diff --git a/plugins/bazaar/src/components/LinkProjectDialog/LinkProjectDialog.tsx b/plugins/bazaar/src/components/LinkProjectDialog/LinkProjectDialog.tsx index e1ef1e217f..3cf474b97a 100644 --- a/plugins/bazaar/src/components/LinkProjectDialog/LinkProjectDialog.tsx +++ b/plugins/bazaar/src/components/LinkProjectDialog/LinkProjectDialog.tsx @@ -15,13 +15,11 @@ */ import React, { useState } from 'react'; -import { - Dialog, - DialogActions, - Button, - DialogContent, - makeStyles, -} from '@material-ui/core'; +import Dialog from '@material-ui/core/Dialog'; +import DialogActions from '@material-ui/core/DialogActions'; +import Button from '@material-ui/core/Button'; +import DialogContent from '@material-ui/core/DialogContent'; +import { makeStyles } from '@material-ui/core/styles'; import { ProjectSelector } from '../ProjectSelector'; import { CustomDialogTitle } from '../CustomDialogTitle'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; diff --git a/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx index eb125d2111..46b64c9f5d 100644 --- a/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx +++ b/plugins/bazaar/src/components/ProjectCard/ProjectCard.tsx @@ -16,14 +16,12 @@ import React, { useState } from 'react'; import { ItemCardHeader } from '@backstage/core-components'; -import { - Card, - CardActionArea, - CardContent, - Dialog, - makeStyles, - Typography, -} from '@material-ui/core'; +import Card from '@material-ui/core/Card'; +import CardActionArea from '@material-ui/core/CardActionArea'; +import CardContent from '@material-ui/core/CardContent'; +import Dialog from '@material-ui/core/Dialog'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; import { StatusTag } from '../StatusTag/StatusTag'; import { BazaarProject } from '../../types'; import { DateTime } from 'luxon'; diff --git a/plugins/bazaar/src/components/ProjectDialog/ProjectDialog.tsx b/plugins/bazaar/src/components/ProjectDialog/ProjectDialog.tsx index 3a0d156fd8..3ec0c87cfe 100644 --- a/plugins/bazaar/src/components/ProjectDialog/ProjectDialog.tsx +++ b/plugins/bazaar/src/components/ProjectDialog/ProjectDialog.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; -import { Button, Dialog } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import Dialog from '@material-ui/core/Dialog'; import { useForm, UseFormReset, UseFormGetValues } from 'react-hook-form'; import { InputField } from '../InputField/InputField'; import { InputSelector } from '../InputSelector/InputSelector'; diff --git a/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx index 39319b6353..622b107c8f 100644 --- a/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx +++ b/plugins/bazaar/src/components/ProjectPreview/ProjectPreview.tsx @@ -16,13 +16,11 @@ import React, { ChangeEvent, useState } from 'react'; import { ProjectCard } from '../ProjectCard/ProjectCard'; -import { - Box, - makeStyles, - Grid, - TablePagination, - GridSize, -} from '@material-ui/core'; +import Box from '@material-ui/core/Box'; +import Grid from '@material-ui/core/Grid'; +import TablePagination from '@material-ui/core/TablePagination'; +import { GridSize } from '@material-ui/core/Grid'; +import { makeStyles } from '@material-ui/core/styles'; import { BazaarProject } from '../../types'; import { Entity } from '@backstage/catalog-model'; diff --git a/plugins/bazaar/src/components/ProjectSelector/ProjectSelector.tsx b/plugins/bazaar/src/components/ProjectSelector/ProjectSelector.tsx index 41ddacceb4..00553da7d7 100644 --- a/plugins/bazaar/src/components/ProjectSelector/ProjectSelector.tsx +++ b/plugins/bazaar/src/components/ProjectSelector/ProjectSelector.tsx @@ -17,8 +17,9 @@ import React from 'react'; import { Entity } from '@backstage/catalog-model'; import Typography from '@material-ui/core/Typography'; -import { Autocomplete } from '@material-ui/lab'; -import { TextField, makeStyles } from '@material-ui/core'; +import Autocomplete from '@material-ui/lab/Autocomplete'; +import TextField from '@material-ui/core/TextField'; +import { makeStyles } from '@material-ui/core/styles'; type Props = { catalogEntities: Entity[]; diff --git a/plugins/bazaar/src/components/SortMethodSelector/SortMethodSelector.tsx b/plugins/bazaar/src/components/SortMethodSelector/SortMethodSelector.tsx index 2ce7f623d1..b2851b667b 100644 --- a/plugins/bazaar/src/components/SortMethodSelector/SortMethodSelector.tsx +++ b/plugins/bazaar/src/components/SortMethodSelector/SortMethodSelector.tsx @@ -15,7 +15,10 @@ */ import React, { ChangeEvent, ReactNode } from 'react'; -import { FormControl, MenuItem, Select, makeStyles } from '@material-ui/core'; +import FormControl from '@material-ui/core/FormControl'; +import MenuItem from '@material-ui/core/MenuItem'; +import Select from '@material-ui/core/Select'; +import { makeStyles } from '@material-ui/core/styles'; const useStyles = makeStyles({ select: { diff --git a/plugins/bazaar/src/components/SortView/SortView.tsx b/plugins/bazaar/src/components/SortView/SortView.tsx index aa310ba55d..427f3c1ff1 100644 --- a/plugins/bazaar/src/components/SortView/SortView.tsx +++ b/plugins/bazaar/src/components/SortView/SortView.tsx @@ -18,14 +18,15 @@ import React, { ChangeEvent, useEffect, useState } from 'react'; import { Content, SupportButton } from '@backstage/core-components'; import { AddProjectDialog } from '../AddProjectDialog'; import { ProjectPreview } from '../ProjectPreview/ProjectPreview'; -import { Button, makeStyles } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; +import { makeStyles } from '@material-ui/core/styles'; import useAsyncFn from 'react-use/lib/useAsyncFn'; import { Entity, stringifyEntityRef } from '@backstage/catalog-model'; import { useApi } from '@backstage/core-plugin-api'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; import { BazaarProject } from '../../types'; import { bazaarApiRef } from '../../api'; -import { Alert } from '@material-ui/lab'; +import Alert from '@material-ui/lab/Alert'; import SearchBar from 'material-ui-search-bar'; import { sortByDate, diff --git a/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx index fa40756a44..34087f1b36 100644 --- a/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx +++ b/plugins/catalog/src/components/CatalogTable/PaginatedCatalogTable.tsx @@ -32,7 +32,7 @@ type PaginatedCatalogTableProps = { * @internal */ export function PaginatedCatalogTable(props: PaginatedCatalogTableProps) { - const { columns, data, next, prev, title, isLoading } = props; + const { columns, data, next, prev, title, isLoading, options } = props; const { updateFilters } = useEntityList(); return ( @@ -41,6 +41,8 @@ export function PaginatedCatalogTable(props: PaginatedCatalogTableProps) { columns={columns} data={data} options={{ + ...options, + // These settings are configured to force server side pagination paginationPosition: 'both', pageSizeOptions: [], showFirstLastPageButtons: false, diff --git a/plugins/circleci/.eslintrc.js b/plugins/circleci/.eslintrc.js index e2a53a6ad2..9d5b45a010 100644 --- a/plugins/circleci/.eslintrc.js +++ b/plugins/circleci/.eslintrc.js @@ -1 +1,5 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); \ No newline at end of file diff --git a/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx b/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx index 8a5dc1c47f..e541669774 100644 --- a/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx +++ b/plugins/circleci/src/components/BuildWithStepsPage/BuildWithStepsPage.tsx @@ -17,7 +17,9 @@ import React, { useEffect } from 'react'; import { useParams } from 'react-router-dom'; import { BuildWithSteps, BuildStepAction } from '../../api'; -import { Grid, Box, Typography } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; +import Box from '@material-ui/core/Box'; +import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import { ActionOutput } from './lib/ActionOutput/ActionOutput'; import LaunchIcon from '@material-ui/icons/Launch'; diff --git a/plugins/circleci/src/components/BuildWithStepsPage/lib/ActionOutput/ActionOutput.tsx b/plugins/circleci/src/components/BuildWithStepsPage/lib/ActionOutput/ActionOutput.tsx index 4a4a8a45f2..a40503552f 100644 --- a/plugins/circleci/src/components/BuildWithStepsPage/lib/ActionOutput/ActionOutput.tsx +++ b/plugins/circleci/src/components/BuildWithStepsPage/lib/ActionOutput/ActionOutput.tsx @@ -15,12 +15,10 @@ */ import { LogViewer } from '@backstage/core-components'; -import { - Accordion, - AccordionDetails, - AccordionSummary, - Typography, -} from '@material-ui/core'; +import Accordion from '@material-ui/core/Accordion'; +import AccordionDetails from '@material-ui/core/AccordionDetails'; +import AccordionSummary from '@material-ui/core/AccordionSummary'; +import Typography from '@material-ui/core/Typography'; import { makeStyles } from '@material-ui/core/styles'; import ExpandMoreIcon from '@material-ui/icons/ExpandMore'; import { BuildStepAction } from 'circleci-api'; diff --git a/plugins/circleci/src/components/BuildsPage/BuildsPage.tsx b/plugins/circleci/src/components/BuildsPage/BuildsPage.tsx index 8d786cf483..e66254510a 100644 --- a/plugins/circleci/src/components/BuildsPage/BuildsPage.tsx +++ b/plugins/circleci/src/components/BuildsPage/BuildsPage.tsx @@ -15,7 +15,7 @@ */ import React from 'react'; import { Builds } from './lib/Builds'; -import { Grid } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; export const BuildsPage = () => ( diff --git a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx index 248275fb77..d271b21bc9 100644 --- a/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx +++ b/plugins/circleci/src/components/BuildsPage/lib/CITable/CITable.tsx @@ -15,14 +15,12 @@ */ import React from 'react'; -import { - Avatar, - Typography, - Box, - IconButton, - makeStyles, - Tooltip, -} from '@material-ui/core'; +import Avatar from '@material-ui/core/Avatar'; +import Typography from '@material-ui/core/Typography'; +import Box from '@material-ui/core/Box'; +import IconButton from '@material-ui/core/IconButton'; +import Tooltip from '@material-ui/core/Tooltip'; +import { makeStyles } from '@material-ui/core/styles'; import RetryIcon from '@material-ui/icons/Replay'; import GitHubIcon from '@material-ui/icons/GitHub'; import LaunchIcon from '@material-ui/icons/Launch'; diff --git a/plugins/cloudbuild/.eslintrc.js b/plugins/cloudbuild/.eslintrc.js index e2a53a6ad2..9d5b45a010 100644 --- a/plugins/cloudbuild/.eslintrc.js +++ b/plugins/cloudbuild/.eslintrc.js @@ -1 +1,5 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); \ No newline at end of file diff --git a/plugins/cloudbuild/src/components/Cards/Cards.tsx b/plugins/cloudbuild/src/components/Cards/Cards.tsx index 5d837cce68..572ccceb58 100644 --- a/plugins/cloudbuild/src/components/Cards/Cards.tsx +++ b/plugins/cloudbuild/src/components/Cards/Cards.tsx @@ -19,7 +19,8 @@ import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; import { WorkflowRunsTable } from '../WorkflowRunsTable'; import { useEntity } from '@backstage/plugin-catalog-react'; import { WorkflowRunStatus } from '../WorkflowRunStatus'; -import { makeStyles, LinearProgress } from '@material-ui/core'; +import LinearProgress from '@material-ui/core/LinearProgress'; +import { makeStyles } from '@material-ui/core/styles'; import ExternalLinkIcon from '@material-ui/icons/Launch'; import { CLOUDBUILD_ANNOTATION } from '../useProjectName'; import { getLocation } from '../useLocation'; diff --git a/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx b/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx index 1c9bdcbf5f..b7ff906c08 100644 --- a/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx +++ b/plugins/cloudbuild/src/components/WorkflowRunDetails/WorkflowRunDetails.tsx @@ -15,18 +15,16 @@ */ import { Entity } from '@backstage/catalog-model'; -import { - Box, - LinearProgress, - makeStyles, - Paper, - Table, - TableBody, - TableCell, - TableContainer, - TableRow, - Typography, -} from '@material-ui/core'; +import Box from '@material-ui/core/Box'; +import LinearProgress from '@material-ui/core/LinearProgress'; +import Paper from '@material-ui/core/Paper'; +import Table from '@material-ui/core/Table'; +import TableBody from '@material-ui/core/TableBody'; +import TableCell from '@material-ui/core/TableCell'; +import TableContainer from '@material-ui/core/TableContainer'; +import TableRow from '@material-ui/core/TableRow'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles } from '@material-ui/core/styles'; import ExternalLinkIcon from '@material-ui/icons/Launch'; import qs from 'qs'; import React from 'react'; diff --git a/plugins/cloudbuild/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx b/plugins/cloudbuild/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx index 65b5ca149f..cda5f16116 100644 --- a/plugins/cloudbuild/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx +++ b/plugins/cloudbuild/src/components/WorkflowRunsTable/WorkflowRunsTable.tsx @@ -14,7 +14,10 @@ * limitations under the License. */ import React from 'react'; -import { Typography, Box, IconButton, Tooltip } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import Box from '@material-ui/core/Box'; +import IconButton from '@material-ui/core/IconButton'; +import Tooltip from '@material-ui/core/Tooltip'; import RetryIcon from '@material-ui/icons/Replay'; import GoogleIcon from '@material-ui/icons/CloudCircle'; import { useWorkflowRuns, WorkflowRun } from '../useWorkflowRuns'; diff --git a/plugins/explore/.eslintrc.js b/plugins/explore/.eslintrc.js index e2a53a6ad2..a70295ae42 100644 --- a/plugins/explore/.eslintrc.js +++ b/plugins/explore/.eslintrc.js @@ -1 +1,6 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); + \ No newline at end of file diff --git a/plugins/explore/api-report.md b/plugins/explore/api-report.md index 532b853671..b6bc769800 100644 --- a/plugins/explore/api-report.md +++ b/plugins/explore/api-report.md @@ -23,7 +23,7 @@ import { ReactNode } from 'react'; import { ResultHighlight } from '@backstage/plugin-search-common'; import { RouteRef } from '@backstage/core-plugin-api'; import { SearchResultListItemExtensionProps } from '@backstage/plugin-search-react'; -import { TabProps } from '@material-ui/core'; +import { TabProps } from '@material-ui/core/Tab'; // @public @deprecated (undocumented) export const catalogEntityRouteRef: ExternalRouteRef< diff --git a/plugins/explore/src/components/CatalogKindExploreContent/CatalogKindExploreContent.tsx b/plugins/explore/src/components/CatalogKindExploreContent/CatalogKindExploreContent.tsx index 69607b58da..07a2a0eae1 100644 --- a/plugins/explore/src/components/CatalogKindExploreContent/CatalogKindExploreContent.tsx +++ b/plugins/explore/src/components/CatalogKindExploreContent/CatalogKindExploreContent.tsx @@ -16,7 +16,7 @@ import { Entity } from '@backstage/catalog-model'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { Button } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; import React from 'react'; import useAsync from 'react-use/lib/useAsync'; import { EntityCard } from '../EntityCard'; diff --git a/plugins/explore/src/components/DomainCard/DomainCard.tsx b/plugins/explore/src/components/DomainCard/DomainCard.tsx index c70df46b1a..1f6b234e2a 100644 --- a/plugins/explore/src/components/DomainCard/DomainCard.tsx +++ b/plugins/explore/src/components/DomainCard/DomainCard.tsx @@ -21,14 +21,12 @@ import { getEntityRelations, entityRouteRef, } from '@backstage/plugin-catalog-react'; -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 from 'react'; import { LinkButton, ItemCardHeader } from '@backstage/core-components'; diff --git a/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.tsx b/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.tsx index 15c0d650cc..62b44d0076 100644 --- a/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.tsx +++ b/plugins/explore/src/components/DomainExplorerContent/DomainExplorerContent.tsx @@ -16,7 +16,7 @@ import { DomainEntity } from '@backstage/catalog-model'; import { catalogApiRef } from '@backstage/plugin-catalog-react'; -import { Button } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; import React from 'react'; import useAsync from 'react-use/lib/useAsync'; import { diff --git a/plugins/explore/src/components/EntityCard/EntityCard.tsx b/plugins/explore/src/components/EntityCard/EntityCard.tsx index 9589d4721e..a6cb1e14ca 100644 --- a/plugins/explore/src/components/EntityCard/EntityCard.tsx +++ b/plugins/explore/src/components/EntityCard/EntityCard.tsx @@ -21,14 +21,12 @@ import { getEntityRelations, entityRouteRef, } from '@backstage/plugin-catalog-react'; -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 from 'react'; import { LinkButton, ItemCardHeader } from '@backstage/core-components'; diff --git a/plugins/explore/src/components/ExploreLayout/ExploreLayout.tsx b/plugins/explore/src/components/ExploreLayout/ExploreLayout.tsx index 3ddf0b17f8..6ad36675cf 100644 --- a/plugins/explore/src/components/ExploreLayout/ExploreLayout.tsx +++ b/plugins/explore/src/components/ExploreLayout/ExploreLayout.tsx @@ -19,7 +19,7 @@ import { attachComponentData, useElementFilter, } from '@backstage/core-plugin-api'; -import { TabProps } from '@material-ui/core'; +import { TabProps } from '@material-ui/core/Tab'; import { default as React } from 'react'; // TODO: This layout could be a shared based component if it was possible to create custom TabbedLayouts diff --git a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx index dd0705908a..fe7367cfb9 100644 --- a/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx +++ b/plugins/explore/src/components/GroupsExplorerContent/GroupsDiagram.tsx @@ -33,7 +33,8 @@ import { getEntityRelations, EntityDisplayName, } from '@backstage/plugin-catalog-react'; -import { makeStyles, Typography, useTheme } from '@material-ui/core'; +import Typography from '@material-ui/core/Typography'; +import { makeStyles, useTheme } from '@material-ui/core/styles'; import ZoomOutMap from '@material-ui/icons/ZoomOutMap'; import classNames from 'classnames'; import React from 'react'; diff --git a/plugins/explore/src/components/ToolCard/ToolCard.tsx b/plugins/explore/src/components/ToolCard/ToolCard.tsx index 47c2cfb41d..55631bbd91 100644 --- a/plugins/explore/src/components/ToolCard/ToolCard.tsx +++ b/plugins/explore/src/components/ToolCard/ToolCard.tsx @@ -15,17 +15,14 @@ */ import { ExploreTool } from '@backstage/plugin-explore-react'; -import { - Box, - Card, - CardActions, - CardContent, - CardMedia, - Chip, - makeStyles, - Theme, - Typography, -} 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 Typography from '@material-ui/core/Typography'; +import { makeStyles, Theme } from '@material-ui/core/styles'; import { LinkButton } from '@backstage/core-components'; import classNames from 'classnames'; import React from 'react'; diff --git a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx index cb99f1c125..d4a1ab627e 100644 --- a/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx +++ b/plugins/explore/src/components/ToolSearchResultListItem/ToolSearchResultListItem.tsx @@ -15,13 +15,11 @@ */ import React, { ReactNode } from 'react'; -import { - Box, - Chip, - ListItemIcon, - ListItemText, - makeStyles, -} from '@material-ui/core'; +import Box from '@material-ui/core/Box'; +import Chip from '@material-ui/core/Chip'; +import ListItemIcon from '@material-ui/core/ListItemIcon'; +import ListItemText from '@material-ui/core/ListItemText'; +import { makeStyles } from '@material-ui/core/styles'; import { Link } from '@backstage/core-components'; import { IndexableDocument, diff --git a/plugins/kubernetes/.eslintrc.js b/plugins/kubernetes/.eslintrc.js index e2a53a6ad2..9d5b45a010 100644 --- a/plugins/kubernetes/.eslintrc.js +++ b/plugins/kubernetes/.eslintrc.js @@ -1 +1,5 @@ -module.exports = require('@backstage/cli/config/eslint-factory')(__dirname); +module.exports = require('@backstage/cli/config/eslint-factory')(__dirname, { + rules: { + '@backstage/no-top-level-material-ui-4-imports': 'error', + }, + }); \ No newline at end of file diff --git a/plugins/kubernetes/src/KubernetesContent.tsx b/plugins/kubernetes/src/KubernetesContent.tsx index ed00cb9a13..acd1ecc521 100644 --- a/plugins/kubernetes/src/KubernetesContent.tsx +++ b/plugins/kubernetes/src/KubernetesContent.tsx @@ -15,7 +15,8 @@ */ import React from 'react'; -import { Grid, Typography } from '@material-ui/core'; +import Grid from '@material-ui/core/Grid'; +import Typography from '@material-ui/core/Typography'; import { Entity } from '@backstage/catalog-model'; import { ErrorPanel, diff --git a/plugins/kubernetes/src/Router.tsx b/plugins/kubernetes/src/Router.tsx index 8266b1908e..db54d6c513 100644 --- a/plugins/kubernetes/src/Router.tsx +++ b/plugins/kubernetes/src/Router.tsx @@ -22,7 +22,7 @@ import { } from '@backstage/plugin-catalog-react'; import { Route, Routes } from 'react-router-dom'; import { KubernetesContent } from './KubernetesContent'; -import { Button } from '@material-ui/core'; +import Button from '@material-ui/core/Button'; const KUBERNETES_ANNOTATION = 'backstage.io/kubernetes-id'; const KUBERNETES_LABEL_SELECTOR_QUERY_ANNOTATION = diff --git a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts index 5c80fca213..e8cb9daca5 100644 --- a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts +++ b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.test.ts @@ -16,7 +16,10 @@ import { TestDatabaseId, TestDatabases } from '@backstage/backend-test-utils'; import { DatabaseNotificationsStore } from './DatabaseNotificationsStore'; import { Knex } from 'knex'; -import { Notification } from '@backstage/plugin-notifications-common'; +import { + Notification, + NotificationSeverity, +} from '@backstage/plugin-notifications-common'; jest.setTimeout(60_000); @@ -48,6 +51,7 @@ const id4 = '04e0871e-e60a-4f68-8110-5ae3513f992e'; const id5 = '05e0871e-e60a-4f68-8110-5ae3513f992e'; const id6 = '06e0871e-e60a-4f68-8110-5ae3513f992e'; const id7 = '07e0871e-e60a-4f68-8110-5ae3513f992e'; +const ids = [id1, id2, id3, id4, id5, id6, id7]; const now = Date.now(); const timeDelay = 5 * 1000; /* 5 secs */ @@ -269,6 +273,64 @@ describe.each(databases.eachSupportedId())( }); }); + describe('getNotifications filters on severity', () => { + beforeEach(async () => { + const severities: (NotificationSeverity | undefined)[] = [ + 'normal', + undefined, + 'critical', + 'high', + 'low', + ]; + await Promise.all( + severities.map((severity, idx) => + storage.saveNotification({ + id: ids[idx], + user, + origin: 'test-origin', + created: new Date(now - idx * timeDelay), + payload: { + title: severity || 'default', + severity, + }, + }), + ), + ); + }); + it('normal', async () => { + const normal = await storage.getNotifications({ + user, + minimumSeverity: 'normal', + }); + expect(normal.map(idOnly)).toEqual([id1, id2, id3, id4]); + }); + + it('critical', async () => { + const critical = await storage.getNotifications({ + user, + minimumSeverity: 'critical', + }); + expect(critical.length).toBe(1); + expect(critical.at(0)?.id).toEqual(id3); + }); + + it('high', async () => { + const high = await storage.getNotifications({ + user, + minimumSeverity: 'high', + }); + expect(high.map(idOnly)).toEqual([id3, id4]); + }); + + it('low', async () => { + const low = await storage.getNotifications({ + user, + minimumSeverity: 'low', + }); + expect(low.map(idOnly)).toEqual([id1, id2, id3, id4, id5]); + }); + }); + describe('getNotifications pagination', () => { beforeEach(async () => { await storage.saveNotification(testNotification1); @@ -455,13 +517,14 @@ describe.each(databases.eachSupportedId())( payload: { title: 'New notification', link: '/scaffolder/task/1234', - severity: 'normal', + severity: 'low', }, } as any, }); expect(existing).not.toBeNull(); expect(existing?.id).toEqual(id2); expect(existing?.payload.title).toEqual('New notification'); + expect(existing?.payload.severity).toEqual('low'); expect(existing?.read).toBeNull(); }); diff --git a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts index 59fb58a48f..891b03a889 100644 --- a/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts +++ b/plugins/notifications-backend/src/database/DatabaseNotificationsStore.ts @@ -22,7 +22,10 @@ import { NotificationModifyOptions, NotificationsStore, } from './NotificationsStore'; -import { Notification } from '@backstage/plugin-notifications-common'; +import { + Notification, + NotificationSeverity, +} from '@backstage/plugin-notifications-common'; import { Knex } from 'knex'; const migrationsDir = resolvePackagePath( @@ -46,6 +49,21 @@ const NOTIFICATION_COLUMNS = [ 'saved', ]; +const severities: NotificationSeverity[] = [ + 'critical', + 'high', + 'normal', + 'low', +]; + +export const normalizeSeverity = (input?: string): NotificationSeverity => { + let lower = (input ?? 'normal').toLowerCase() as NotificationSeverity; + if (severities.indexOf(lower) < 0) { + lower = 'normal'; + } + return lower; +}; + /** @internal */ export class DatabaseNotificationsStore implements NotificationsStore { private isSQLite = false; @@ -107,7 +125,7 @@ export class DatabaseNotificationsStore implements NotificationsStore { link: notification.payload?.link, title: notification.payload?.title, description: notification.payload?.description, - severity: notification.payload?.severity, + severity: normalizeSeverity(notification.payload?.severity), scope: notification.payload?.scope, saved: notification.saved, read: notification.read, @@ -198,6 +216,12 @@ export class DatabaseNotificationsStore implements NotificationsStore { query.whereNull('saved'); } // or match both if undefined + if (options.minimumSeverity !== undefined) { + const idx = severities.indexOf(options.minimumSeverity); + const equalOrHigher = severities.slice(0, idx + 1); + query.whereIn('notification.severity', equalOrHigher); + } + return query; }; @@ -296,17 +320,20 @@ export class DatabaseNotificationsStore implements NotificationsStore { return rows[0] as Notification; } - async restoreExistingNotification(options: { + async restoreExistingNotification({ + id, + notification, + }: { id: string; notification: Notification; }) { const updateColumns = { - title: options.notification.payload.title, - description: options.notification.payload.description, - link: options.notification.payload.link, - topic: options.notification.payload.topic, + title: notification.payload.title, + description: notification.payload.description, + link: notification.payload.link, + topic: notification.payload.topic, updated: new Date(), - severity: options.notification.payload.severity, + severity: normalizeSeverity(notification.payload?.severity), read: null, }; @@ -320,7 +347,7 @@ export class DatabaseNotificationsStore implements NotificationsStore { broadcastQuery.update({ ...updateColumns, read: undefined }), ]); - return await this.getNotification(options); + return await this.getNotification({ id }); } async getNotification(options: { id: string }): Promise { diff --git a/plugins/notifications-backend/src/database/NotificationsStore.ts b/plugins/notifications-backend/src/database/NotificationsStore.ts index 8e7eb48147..77f7df61df 100644 --- a/plugins/notifications-backend/src/database/NotificationsStore.ts +++ b/plugins/notifications-backend/src/database/NotificationsStore.ts @@ -16,6 +16,7 @@ import { Notification, + NotificationSeverity, NotificationStatus, } from '@backstage/plugin-notifications-common'; @@ -32,6 +33,7 @@ export type NotificationGetOptions = { read?: boolean; saved?: boolean; createdAfter?: Date; + minimumSeverity?: NotificationSeverity; }; /** @internal */ diff --git a/plugins/notifications-backend/src/service/router.ts b/plugins/notifications-backend/src/service/router.ts index e4a374e580..4a24763e40 100644 --- a/plugins/notifications-backend/src/service/router.ts +++ b/plugins/notifications-backend/src/service/router.ts @@ -18,6 +18,7 @@ import express, { Request } from 'express'; import Router from 'express-promise-router'; import { DatabaseNotificationsStore, + normalizeSeverity, NotificationGetOptions, } from '../database'; import { v4 as uuid } from 'uuid'; @@ -236,6 +237,11 @@ export async function createRouter( } opts.createdAfter = new Date(sinceEpoch); } + if (req.query.minimal_severity) { + opts.minimumSeverity = normalizeSeverity( + req.query.minimal_severity.toString(), + ); + } const [notifications, totalCount] = await Promise.all([ store.getNotifications(opts), diff --git a/plugins/notifications/api-report.md b/plugins/notifications/api-report.md index be57d9da73..11c671112a 100644 --- a/plugins/notifications/api-report.md +++ b/plugins/notifications/api-report.md @@ -11,6 +11,7 @@ import { DiscoveryApi } from '@backstage/core-plugin-api'; import { FetchApi } from '@backstage/core-plugin-api'; import { JSX as JSX_2 } from 'react'; import { Notification as Notification_2 } from '@backstage/plugin-notifications-common'; +import { NotificationSeverity } from '@backstage/plugin-notifications-common'; import { NotificationStatus } from '@backstage/plugin-notifications-common'; import { default as React_2 } from 'react'; import { RouteRef } from '@backstage/core-plugin-api'; @@ -26,6 +27,7 @@ export type GetNotificationsOptions = { createdAfter?: Date; sort?: 'created' | 'topic' | 'origin'; sortOrder?: 'asc' | 'desc'; + minimumSeverity?: NotificationSeverity; }; // @public (undocumented) diff --git a/plugins/notifications/src/api/NotificationsApi.ts b/plugins/notifications/src/api/NotificationsApi.ts index 8e80f5908c..234e86ff13 100644 --- a/plugins/notifications/src/api/NotificationsApi.ts +++ b/plugins/notifications/src/api/NotificationsApi.ts @@ -16,6 +16,7 @@ import { createApiRef } from '@backstage/core-plugin-api'; import { Notification, + NotificationSeverity, NotificationStatus, } from '@backstage/plugin-notifications-common'; @@ -34,6 +35,7 @@ export type GetNotificationsOptions = { createdAfter?: Date; sort?: 'created' | 'topic' | 'origin'; sortOrder?: 'asc' | 'desc'; + minimumSeverity?: NotificationSeverity; }; /** @public */ diff --git a/plugins/notifications/src/api/NotificationsClient.ts b/plugins/notifications/src/api/NotificationsClient.ts index d98e0080e8..1e2e289bbe 100644 --- a/plugins/notifications/src/api/NotificationsClient.ts +++ b/plugins/notifications/src/api/NotificationsClient.ts @@ -67,6 +67,9 @@ export class NotificationsClient implements NotificationsApi { if (options?.createdAfter !== undefined) { queryString.append('created_after', options.createdAfter.toISOString()); } + if (options?.minimumSeverity !== undefined) { + queryString.append('minimal_severity', options.minimumSeverity); + } const urlSegment = `?${queryString}`; return await this.request(urlSegment); diff --git a/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx b/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx index ad42c03d16..caf966eab3 100644 --- a/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx +++ b/plugins/notifications/src/components/NotificationsFilters/NotificationsFilters.tsx @@ -25,6 +25,7 @@ import { Typography, } from '@material-ui/core'; import { GetNotificationsOptions } from '../../api'; +import { NotificationSeverity } from '@backstage/plugin-notifications-common'; export type SortBy = Required< Pick @@ -39,6 +40,8 @@ export type NotificationsFiltersProps = { onSortingChanged: (sortBy: SortBy) => void; saved?: boolean; onSavedChanged: (checked: boolean | undefined) => void; + severity: NotificationSeverity; + onSeverityChanged: (severity: NotificationSeverity) => void; }; export const CreatedAfterOptions: { @@ -108,6 +111,13 @@ const getSortByText = (sortBy?: SortBy): string => { return 'newest'; }; +const AllSeverityOptions: { [key in NotificationSeverity]: string } = { + critical: 'Critical', + high: 'High', + normal: 'Normal', + low: 'Low', +}; + export const NotificationsFilters = ({ sorting, onSortingChanged, @@ -117,6 +127,8 @@ export const NotificationsFilters = ({ onCreatedAfterChanged, saved, onSavedChanged, + severity, + onSeverityChanged, }: NotificationsFiltersProps) => { const sortByText = getSortByText(sorting); @@ -162,6 +174,14 @@ export const NotificationsFilters = ({ viewValue = 'read'; } + const handleOnSeverityChanged = ( + event: React.ChangeEvent<{ name?: string; value: unknown }>, + ) => { + const value: NotificationSeverity = + (event.target.value as NotificationSeverity) || 'normal'; + onSeverityChanged(value); + }; + return ( <> @@ -169,6 +189,7 @@ export const NotificationsFilters = ({ Filters + View @@ -185,14 +206,16 @@ export const NotificationsFilters = ({ + - + Created after + {Object.keys(AllSeverityOptions).map((key: string) => ( + + {AllSeverityOptions[key as NotificationSeverity]} + + ))} + + + ); diff --git a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx index 54acc5d7bc..e3ad27d40a 100644 --- a/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx +++ b/plugins/notifications/src/components/NotificationsPage/NotificationsPage.tsx @@ -32,6 +32,7 @@ import { SortByOptions, } from '../NotificationsFilters'; import { GetNotificationsOptions } from '../../api'; +import { NotificationSeverity } from '@backstage/plugin-notifications-common'; export const NotificationsPage = () => { const [refresh, setRefresh] = React.useState(false); @@ -45,6 +46,7 @@ export const NotificationsPage = () => { const [sorting, setSorting] = React.useState( SortByOptions.newest.sortBy, ); + const [severity, setSeverity] = React.useState('low'); const { error, value, retry, loading } = useNotificationsApi( api => { @@ -52,6 +54,7 @@ export const NotificationsPage = () => { search: containsText, limit: pageSize, offset: pageNumber * pageSize, + minimumSeverity: severity, ...(sorting || {}), }; if (unreadOnly !== undefined) { @@ -76,6 +79,7 @@ export const NotificationsPage = () => { pageSize, sorting, saved, + severity, ], ); @@ -114,6 +118,8 @@ export const NotificationsPage = () => { sorting={sorting} saved={saved} onSavedChanged={setSaved} + severity={severity} + onSeverityChanged={setSeverity} /> diff --git a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx index acbeef8769..8012451cc9 100644 --- a/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx +++ b/plugins/notifications/src/components/NotificationsTable/NotificationsTable.tsx @@ -33,6 +33,7 @@ import MarkAsUnreadIcon from '@material-ui/icons/Markunread' /* TODO: use Drafts import MarkAsReadIcon from '@material-ui/icons/CheckCircle'; import MarkAsUnsavedIcon from '@material-ui/icons/LabelOff' /* TODO: use BookmarkRemove and BookmarkAdd once we have mui 5 icons */; import MarkAsSavedIcon from '@material-ui/icons/Label'; +import { SeverityIcon } from './SeverityIcon'; const ThrottleDelayMs = 1000; @@ -93,6 +94,12 @@ export const NotificationsTable = ({ const compactColumns = React.useMemo( (): TableColumn[] => [ + { + width: '1rem', + render: (notification: Notification) => ( + + ), + }, { customFilterAndSearch: () => true /* Keep it on backend due to pagination. If recent flickering is an issue, implement search here as well. */, diff --git a/plugins/notifications/src/components/NotificationsTable/SeverityIcon.tsx b/plugins/notifications/src/components/NotificationsTable/SeverityIcon.tsx new file mode 100644 index 0000000000..37680db3c2 --- /dev/null +++ b/plugins/notifications/src/components/NotificationsTable/SeverityIcon.tsx @@ -0,0 +1,39 @@ +/* + * Copyright 2024 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 React from 'react'; +import { NotificationSeverity } from '@backstage/plugin-notifications-common'; +import NormalIcon from '@material-ui/icons/CheckOutlined'; +import CriticalIcon from '@material-ui/icons/ErrorOutline'; +import HighIcon from '@material-ui/icons/WarningOutlined'; +import LowIcon from '@material-ui/icons/InfoOutlined'; + +export const SeverityIcon = ({ + severity, +}: { + severity?: NotificationSeverity; +}) => { + switch (severity) { + case 'critical': + return ; + case 'high': + return ; + case 'low': + return ; + case 'normal': + default: + return ; + } +}; diff --git a/yarn.lock b/yarn.lock index 0f498305c3..a0d94a3027 100644 --- a/yarn.lock +++ b/yarn.lock @@ -3691,6 +3691,7 @@ __metadata: nodemon: ^3.0.1 npm-packlist: ^5.0.0 ora: ^5.3.0 + p-limit: ^3.1.0 p-queue: ^6.6.2 postcss: ^8.1.0 process: ^0.11.10 @@ -18735,12 +18736,12 @@ __metadata: linkType: hard "@types/dockerode@npm:^3.3.0, @types/dockerode@npm:^3.3.21": - version: 3.3.24 - resolution: "@types/dockerode@npm:3.3.24" + version: 3.3.26 + resolution: "@types/dockerode@npm:3.3.26" dependencies: "@types/docker-modem": "*" "@types/node": "*" - checksum: 00329ba9225f5b57bfc0ba8c4dddb17100ebe13c5192fe8a14fce59eec456d258e814b6c78df26d7d7bb878fc38455f559f278490c9c8efad8f708335643b40e + checksum: ec1e83ef2d938813c8fa72f7c8744a9bf598369d8a0f340377ddff25c6e7d118379cd297eecbe4af2b7aa64bf5cd1bb66b32d1e3874a062433b967265be94f09 languageName: node linkType: hard