diff --git a/docs/GETTING_STARTED.md b/docs/GETTING_STARTED.md index d93eb702dec..0b09c94ba73 100644 --- a/docs/GETTING_STARTED.md +++ b/docs/GETTING_STARTED.md @@ -23,7 +23,7 @@ $ curl https://get.volta.sh | bash - ## Add nvm to your .*rc file, or open a new terminal window. + ## Add volta to your .*rc file, or open a new terminal window. $ volta install node@18.14.1 @@ -42,26 +42,25 @@ 10. Navigate to the root directory of the repository, then start Cloud Manager and the JS client with `yarn up`. 11. After installation, Cloud Manager should be running at http://localhost:3000. -## Serving a production build of Cloud Manager: +## Serving a production build of Cloud Manager -Since Cloud Manager was generated using Create React App, `yarn build` can be used to generate an optimized production bundle: +You can then serve these files however you prefer or use our included local http server. ```bash +yarn install:all - yarn install:all - - yarn workspace linode-manager build +yarn workspace linode-manager build +yarn workspace linode-manager run start:ci ``` -You can then serve these files however you prefer, for example, with [http-server](https://www.npmjs.com/package/http-server): - -```bash - - npm install -g http-server +## Exposing Cloud Manager's dev server to the network - cd packages/manager/build +By default, Cloud Manager's dev server only listens on `localhost`. If you need to +expose the Vite dev server, you can use the following command. - http-server . +> **Note**: This is useful for running Cloud Manager's dev server in Docker-like environments -``` +```bash +yarn up:expose +``` \ No newline at end of file diff --git a/docs/development-guide/04-component-library.md b/docs/development-guide/04-component-library.md index 16a1b684671..b66e19046eb 100644 --- a/docs/development-guide/04-component-library.md +++ b/docs/development-guide/04-component-library.md @@ -7,7 +7,7 @@ We use [Material-UI](https://mui.com/material-ui/getting-started/overview/) as t All MUI components have abstractions in the Cloud Manager codebase, meaning you will use relative imports to use them instead of importing from MUI directly: ```ts -import Typography from "src/components/core/Typography"; // NOT from '@mui/material/Typography' +import { Typography } from "src/components/Typography"; // NOT from '@mui/material/Typography' ``` We do this because it gives us the ability to customize the component and still keep imports consistent. It also gives us flexibility if we ever wanted to change out the underlying component library. diff --git a/package.json b/package.json index ecbc01e5081..73062fa178b 100644 --- a/package.json +++ b/package.json @@ -28,7 +28,7 @@ "up:expose": "yarn install:all && yarn build:validation && yarn build:sdk && yarn start:all:expose", "dev": "yarn install:all && yarn start:all", "start:all": "concurrently -n api-v4,validation,manager -c blue,yellow,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace linode-manager start\"", - "start:all:expose": "concurrently -n api-v4,validation,manager -c blue,yellow,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace linode-manager start --host\"", + "start:all:expose": "concurrently -n api-v4,validation,manager -c blue,yellow,green \"yarn workspace @linode/api-v4 start\" \"yarn workspace @linode/validation start\" \"yarn workspace linode-manager start:expose\"", "start:manager": "yarn workspace linode-manager start", "start:manager:ci": "yarn workspace linode-manager start:ci", "clean": "rm -rf node_modules && rm -rf packages/@linode/api-v4/node_modules && rm -rf packages/manager/node_modules && rm -rf packages/@linode/validation/node_modules", diff --git a/packages/api-v4/CHANGELOG.md b/packages/api-v4/CHANGELOG.md index 17811bae3c5..259e59b9194 100644 --- a/packages/api-v4/CHANGELOG.md +++ b/packages/api-v4/CHANGELOG.md @@ -1,3 +1,16 @@ +## [2023-07-11] - v0.96.0 + + +### Added: + +- Endpoints for VPC ([#9361](https://github.com/linode/manager/pull/9361)) +- Endpoints for the Akamai Global Load Balancer ([#9363](https://github.com/linode/manager/pull/9363)) + +### Changed: + +- Use 'canceled' instead of 'cancelled' for EntityTransferStatus ([#9335](https://github.com/linode/manager/pull/9335)) + + ## [2023-06-27] - v0.95.1 diff --git a/packages/api-v4/package.json b/packages/api-v4/package.json index 4920f6ba031..050bddfda81 100644 --- a/packages/api-v4/package.json +++ b/packages/api-v4/package.json @@ -1,6 +1,6 @@ { "name": "@linode/api-v4", - "version": "0.95.1", + "version": "0.96.0", "homepage": "https://github.com/linode/manager/tree/develop/packages/api-v4", "bugs": { "url": "https://github.com/linode/manager/issues" diff --git a/packages/api-v4/src/aglb/entrypoints.ts b/packages/api-v4/src/aglb/entrypoints.ts new file mode 100644 index 00000000000..a650284e756 --- /dev/null +++ b/packages/api-v4/src/aglb/entrypoints.ts @@ -0,0 +1,68 @@ +import Request, { setData, setMethod, setURL } from '../request'; +import { ResourcePage } from 'src/types'; +import { BETA_API_ROOT } from 'src/constants'; +import type { + CreateEntrypointPayload, + Entrypoint, + EntrypointPayload, +} from './types'; + +/** + * getEntrypoints + * + * Returns a paginated list of Akamai Global Load Balancer entry points + */ +export const getEntrypoints = () => + Request>( + setURL(`${BETA_API_ROOT}/aglb/entrypoints`), + setMethod('GET') + ); + +/** + * getEntrypoint + * + * Returns an Akamai Global Load Balancer entry point + */ +export const getEntrypoint = (id: number) => + Request( + setURL(`${BETA_API_ROOT}/aglb/entrypoints/${encodeURIComponent(id)}`), + setMethod('GET') + ); + +/** + * createEntrypoint + * + * Creates an Akamai Global Load Balancer entry point + */ +export const createEntrypoint = (data: CreateEntrypointPayload) => + Request( + setURL(`${BETA_API_ROOT}/aglb/entrypoints`), + setData(data), + setMethod('POST') + ); + +/** + * updateEntrypoint + * + * Updates an Akamai Global Load Balancer entry point + */ +export const updateEntrypoint = ( + id: number, + data: Partial +) => + Request( + setURL(`${BETA_API_ROOT}/aglb/entrypoints/${encodeURIComponent(id)}`), + setData(data), + setMethod('POST') + ); + +/** + * deleteEntrypoint + * + * Deletes an Akamai Global Load Balancer entry point + */ +export const deleteEntrypoint = (id: number) => + Request<{}>( + setURL(`${BETA_API_ROOT}/aglb/entrypoints/${encodeURIComponent(id)}`), + setMethod('DELETE') + ); diff --git a/packages/api-v4/src/aglb/loadbalancers.ts b/packages/api-v4/src/aglb/loadbalancers.ts new file mode 100644 index 00000000000..df6a0757cba --- /dev/null +++ b/packages/api-v4/src/aglb/loadbalancers.ts @@ -0,0 +1,68 @@ +import Request, { setData, setMethod, setURL } from '../request'; +import { BETA_API_ROOT } from 'src/constants'; +import { ResourcePage } from 'src/types'; +import type { + CreateLoadbalancerPayload, + Loadbalancer, + UpdateLoadbalancerPayload, +} from './types'; + +/** + * getLoadbalancers + * + * Returns a paginated list of Akamai Global Load Balancers + */ +export const getLoadbalancers = () => + Request>( + setURL(`${BETA_API_ROOT}/aglb/loadbalancers`), + setMethod('GET') + ); + +/** + * getLoadbalancer + * + * Returns an Akamai Global Load Balancer + */ +export const getLoadbalancer = (id: number) => + Request( + setURL(`${BETA_API_ROOT}/aglb/loadbalancers/${encodeURIComponent(id)}`), + setMethod('GET') + ); + +/** + * createLoadbalancer + * + * Creates an Akamai Global Load Balancer + */ +export const createLoadbalancer = (data: CreateLoadbalancerPayload) => + Request( + setURL(`${BETA_API_ROOT}/aglb/loadbalancers`), + setData(data), + setMethod('POST') + ); + +/** + * updateLoadbalancer + * + * Updates an Akamai Global Load Balancer + */ +export const updateLoadbalancer = ( + id: number, + data: UpdateLoadbalancerPayload +) => + Request( + setURL(`${BETA_API_ROOT}/aglb/loadbalancers/${encodeURIComponent(id)}`), + setData(data), + setMethod('POST') + ); + +/** + * deleteLoadbalancer + * + * Deletes an Akamai Global Load Balancer + */ +export const deleteLoadbalancer = (id: number) => + Request<{}>( + setURL(`${BETA_API_ROOT}/aglb/loadbalancers/${encodeURIComponent(id)}`), + setMethod('DELETE') + ); diff --git a/packages/api-v4/src/aglb/routes.ts b/packages/api-v4/src/aglb/routes.ts new file mode 100644 index 00000000000..7bd9be61e8d --- /dev/null +++ b/packages/api-v4/src/aglb/routes.ts @@ -0,0 +1,61 @@ +import Request, { setData, setMethod, setURL } from '../request'; +import { ResourcePage } from 'src/types'; +import { BETA_API_ROOT } from 'src/constants'; +import type { Route, RoutePayload } from './types'; + +/** + * getRoutes + * + * Returns a paginated list of Akamai Global Load Balancer routes + */ +export const getRoutes = () => + Request>( + setURL(`${BETA_API_ROOT}/aglb/routes`), + setMethod('GET') + ); + +/** + * getRoute + * + * Returns an Akamai Global Load Balancer route + */ +export const getRoute = (id: number) => + Request( + setURL(`${BETA_API_ROOT}/aglb/routes/${encodeURIComponent(id)}`), + setMethod('GET') + ); + +/** + * createRoute + * + * Creates an Akamai Global Load Balancer route + */ +export const createRoute = (data: RoutePayload) => + Request( + setURL(`${BETA_API_ROOT}/aglb/routes`), + setData(data), + setMethod('POST') + ); + +/** + * updateRoute + * + * Updates an Akamai Global Load Balancer route + */ +export const updateRoute = (id: number, data: Partial) => + Request( + setURL(`${BETA_API_ROOT}/aglb/routes/${encodeURIComponent(id)}`), + setData(data), + setMethod('POST') + ); + +/** + * deleteRoute + * + * Deletes an Akamai Global Load Balancer route + */ +export const deleteRoute = (id: number) => + Request<{}>( + setURL(`${BETA_API_ROOT}/aglb/routes/${encodeURIComponent(id)}`), + setMethod('DELETE') + ); diff --git a/packages/api-v4/src/aglb/service-targets.ts b/packages/api-v4/src/aglb/service-targets.ts new file mode 100644 index 00000000000..d1447ca0ffe --- /dev/null +++ b/packages/api-v4/src/aglb/service-targets.ts @@ -0,0 +1,64 @@ +import Request, { setData, setMethod, setURL } from '../request'; +import { ResourcePage } from 'src/types'; +import { BETA_API_ROOT } from 'src/constants'; +import type { ServiceTarget, ServiceTargetPayload } from './types'; + +/** + * getServiceTargets + * + * Returns a paginated list of Akamai Global Load Balancer service targets + */ +export const getServiceTargets = () => + Request>( + setURL(`${BETA_API_ROOT}/aglb/service-targets`), + setMethod('GET') + ); + +/** + * getServiceTarget + * + * Returns an Akamai Global Load Balancer route + */ +export const getServiceTarget = (id: number) => + Request( + setURL(`${BETA_API_ROOT}/aglb/service-targets/${encodeURIComponent(id)}`), + setMethod('GET') + ); + +/** + * createServiceTarget + * + * Creates an Akamai Global Load Balancer route + */ +export const createServiceTarget = (data: ServiceTargetPayload) => + Request( + setURL(`${BETA_API_ROOT}/aglb/service-targets`), + setData(data), + setMethod('POST') + ); + +/** + * updateServiceTarget + * + * Updates an Akamai Global Load Balancer route + */ +export const updateServiceTarget = ( + id: number, + data: Partial +) => + Request( + setURL(`${BETA_API_ROOT}/aglb/service-targets/${encodeURIComponent(id)}`), + setData(data), + setMethod('POST') + ); + +/** + * deleteServiceTarget + * + * Deletes an Akamai Global Load Balancer service target + */ +export const deleteServiceTarget = (id: number) => + Request<{}>( + setURL(`${BETA_API_ROOT}/aglb/service-targets/${encodeURIComponent(id)}`), + setMethod('DELETE') + ); diff --git a/packages/api-v4/src/aglb/types.ts b/packages/api-v4/src/aglb/types.ts new file mode 100644 index 00000000000..562e85da5eb --- /dev/null +++ b/packages/api-v4/src/aglb/types.ts @@ -0,0 +1,92 @@ +export interface Loadbalancer { + id: number; + tags: string[]; + label: string; + regions: string[]; + entrypoints: string[]; +} + +interface LoadbalancerPayload { + label: string; + regions: string[]; + tags?: string[]; +} + +export interface CreateLoadbalancerPayload extends LoadbalancerPayload { + entrypoints?: EntrypointPayload[]; +} + +export interface UpdateLoadbalancerPayload extends LoadbalancerPayload { + entrypoints: number[]; +} + +type Protocol = 'TCP' | 'HTTP' | 'HTTPS'; + +type Policy = 'ROUND_ROBIN'; + +export interface RoutePayload { + label: string; + rules: Rule[]; +} + +export interface Route extends RoutePayload { + id: number; +} + +export interface EntrypointPayload { + label: string; + port: number; + protocol: Protocol; + certificate_table: CertificateTable[]; + routes: RoutePayload[]; +} + +export type CreateEntrypointPayload = Omit; + +export interface Entrypoint { + id: number; + label: string; + port: number; + protocol: Protocol; + certificate_table: CertificateTable[]; + routes: string[]; +} + +export interface CertificateTable { + sni_hostname: string; + certificate_id: string; +} + +export interface Rule { + match_condition: Match; + service_targets: ServiceTargetPayload[]; + default_target: ServiceTargetPayload; +} + +export interface Match { + path: string; +} + +export interface ServiceTargetPayload { + label: string; + endpoints: Endpoint[]; + ca_certificate: string; + load_balancing_policy: Policy; + health_check_interval: number; + health_check_timeout: number; + health_check_unhealthy_thresh: number; + health_check_healthy_thresh: number; + health_check_path: string; + health_check_host: string; +} + +export interface ServiceTarget extends ServiceTargetPayload { + id: number; +} + +export interface Endpoint { + ip: string; + port: number; + capacity: number; + hard_rate_limit: number; +} diff --git a/packages/api-v4/src/entity-transfers/types.ts b/packages/api-v4/src/entity-transfers/types.ts index b63be6581b6..f9034fbf2c6 100644 --- a/packages/api-v4/src/entity-transfers/types.ts +++ b/packages/api-v4/src/entity-transfers/types.ts @@ -1,7 +1,7 @@ export type EntityTransferStatus = | 'pending' | 'accepted' - | 'cancelled' + | 'canceled' | 'completed' | 'failed' | 'stale'; diff --git a/packages/api-v4/src/index.ts b/packages/api-v4/src/index.ts index 208b44e4ca0..6c74d394cf0 100644 --- a/packages/api-v4/src/index.ts +++ b/packages/api-v4/src/index.ts @@ -1,7 +1,11 @@ export * from './account'; +export * from './databases'; + export * from './domains'; +export * from './entity-transfers'; + export * from './firewalls'; export * from './images'; @@ -16,6 +20,8 @@ export * from './managed'; export * from './networking'; +export * from './nodebalancers'; + export * from './object-storage'; export * from './profile'; @@ -34,11 +40,7 @@ export * from './vlans'; export * from './volumes'; -export * from './nodebalancers'; - -export * from './databases'; - -export * from './entity-transfers'; +export * from './vpcs'; export { baseRequest, diff --git a/packages/api-v4/src/vpcs/index.ts b/packages/api-v4/src/vpcs/index.ts new file mode 100644 index 00000000000..6506438fdc6 --- /dev/null +++ b/packages/api-v4/src/vpcs/index.ts @@ -0,0 +1,3 @@ +export * from './vpcs'; + +export * from './types'; diff --git a/packages/api-v4/src/vpcs/types.ts b/packages/api-v4/src/vpcs/types.ts new file mode 100644 index 00000000000..ca4bc1dcf5f --- /dev/null +++ b/packages/api-v4/src/vpcs/types.ts @@ -0,0 +1,34 @@ +export interface VPC { + id: number; + label: string; + description: string; + region: string; + subnets: Subnet[]; + created: string; + updated: string; +} + +export interface CreateVPCPayload { + label: string; + description?: string; + region: string; + subnets?: SubnetPostObject[]; +} + +export interface UpdateVPCPayload { + label?: string; + description?: string; +} + +export interface SubnetPostObject { + label: string; + ipv4: string; + ipv6: string; +} + +export interface Subnet extends SubnetPostObject { + id: number; + linodes: number[]; + created: string; + updated: string; +} diff --git a/packages/api-v4/src/vpcs/vpcs.ts b/packages/api-v4/src/vpcs/vpcs.ts new file mode 100644 index 00000000000..371bdd1e156 --- /dev/null +++ b/packages/api-v4/src/vpcs/vpcs.ts @@ -0,0 +1,81 @@ +import { + createVPCSchema, + updateVPCSchema, +} from '@linode/validation/lib/vpcs.schema'; +import { BETA_API_ROOT as API_ROOT } from '../constants'; +import Request, { + setData, + setMethod, + setParams, + setURL, + setXFilter, +} from '../request'; +import { Filter, ResourcePage as Page, Params } from '../types'; +import { CreateVPCPayload, UpdateVPCPayload, VPC } from './types'; + +// VPC methods +/** + * getVPCs + * + * Return a paginated list of VPCs on this account. + * + */ +export const getVPCs = (params?: Params, filter?: Filter) => + Request>( + setURL(`${API_ROOT}/vpcs`), + setMethod('GET'), + setParams(params), + setXFilter(filter) + ); + +/** + * getVPC + * + * Return details for a single specified VPC. + * + */ +export const getVPC = (vpcID: number) => + Request( + setURL(`${API_ROOT}/vpcs/${encodeURIComponent(vpcID)}`), + setMethod('GET') + ); + +/** + * createVPC + * + * Create a new VPC in the specified region. + * + */ +export const createVPC = (data: CreateVPCPayload) => + Request( + setURL(`${API_ROOT}/vpcs`), + setMethod('POST'), + setData(data, createVPCSchema) + ); + +/** + * updateVPC + * + * Update a VPC. + * + */ +export const updateVPC = (vpcID: number, data: UpdateVPCPayload) => + Request( + setURL(`${API_ROOT}/vpcs/${encodeURIComponent(vpcID)}`), + setMethod('PUT'), + setData(data, updateVPCSchema) + ); + +/** + * deleteVPC + * + * Delete a single specified VPC. + * + */ +export const deleteVPC = (vpcID: number) => + Request<{}>( + setURL(`${API_ROOT}/vpcs/${encodeURIComponent(vpcID)}`), + setMethod('DELETE') + ); + +// Subnet methods diff --git a/packages/manager/.storybook/preview.tsx b/packages/manager/.storybook/preview.tsx index 13b52204b9f..a7170250d3e 100644 --- a/packages/manager/.storybook/preview.tsx +++ b/packages/manager/.storybook/preview.tsx @@ -25,10 +25,6 @@ MINIMAL_VIEWPORTS.mobile1.styles = { export const DocsContainer = ({ children, context }) => { const isDark = useDarkMode(); - React.useEffect(() => { - worker?.start(); - }, []); - return ( , { theme: isDark ? 'dark' : 'light' }); }, ], + loaders: [ + async () => ({ + msw: await worker?.start(), + }), + ], parameters: { actions: { argTypesRegex: '^on[A-Z].*' }, backgrounds: { diff --git a/packages/manager/CHANGELOG.md b/packages/manager/CHANGELOG.md index ae479346b6f..eb770d074d6 100644 --- a/packages/manager/CHANGELOG.md +++ b/packages/manager/CHANGELOG.md @@ -4,6 +4,64 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](http://keepachangelog.com/) and this project adheres to [Semantic Versioning](http://semver.org/). +## [2023-07-11] - v1.97.0 + + +### Added: + +- Light/dark mode keyboard shortcut copy on "My Settings" page ([#9286](https://github.com/linode/manager/pull/9286)) +- Visual outline to some country flags ([#9288](https://github.com/linode/manager/pull/9288)) +- Helper text for the Add SSH Key Drawer form ([#9290](https://github.com/linode/manager/pull/9290)) +- Improved warning and error messaging for failed backup events ([#9364](https://github.com/linode/manager/pull/9364)) + +### Changed: + +- Update Metadata copy ([#9374](https://github.com/linode/manager/pull/9374)) + +### Fixed: + +- Notification menu crashing older Safari versions ([#9360](https://github.com/linode/manager/pull/9360)) +- Confirmation modal overflow on mobile ([#9289](https://github.com/linode/manager/pull/9289)) +- Layout issue with Create Access Key Drawer for Object Storage ([#9296](https://github.com/linode/manager/pull/9296)) +- LinodeSelectV2 label association ([#9298](https://github.com/linode/manager/pull/9298)) +- Missing icons in DBaaS engine selection field ([#9306](https://github.com/linode/manager/pull/9306)) +- Disable delete button for public IP addresses if it's the only IP address ([#9332](https://github.com/linode/manager/pull/9332)) +- Action Menu tooltip icon color deprecation ([#9352](https://github.com/linode/manager/pull/9352)) +- Multiple requests for logo when loading billing invoice PDFs ([#9355](https://github.com/linode/manager/pull/9355)) +- Updated wording from “Linode” to “Cloud Manager” ([#9358](https://github.com/linode/manager/pull/9358)) +- Volume empty state misspelling of NVMe ([#9366](https://github.com/linode/manager/pull/9366)) + +### Tech Stories: + +- React Query methods for VPC ([#9361](https://github.com/linode/manager/pull/9361)) +- Made yarn up:expose actually expose Cloud Manager on all interfaces ([#9297](https://github.com/linode/manager/pull/9297)) +- MUI v5 Migration - `Components > InlineMenuAction` ([#9268](https://github.com/linode/manager/pull/9268)) +- MUI v5 Migration - `Components > LandingLoading` ([#9282](https://github.com/linode/manager/pull/9282)) +- Upgrade LaunchDarkly client library ([#9285](https://github.com/linode/manager/pull/9285)) +- MUI v5 Migration - `Components > LongviewLineGraph` ([#9291](https://github.com/linode/manager/pull/9291)) +- MUI v5 Migration - `Components > SingleTextFieldForm` ([#9292](https://github.com/linode/manager/pull/9292)) +- MUI v5 Migration - `Components > SelectableTableRow` ([#9299](https://github.com/linode/manager/pull/9299)) +- MUI v5 Migration - `Components > Chip` ([#9310](https://github.com/linode/manager/pull/9310)) +- MUI v5 Migration - `Components > Toolbar` ([#9319](https://github.com/linode/manager/pull/9319)) +- MUI v5 Migration - `Components > Accordion` (part 2) ([#9320](https://github.com/linode/manager/pull/9320)) +- MUI v5 Migration - `Components > AppBar` ([#9321](https://github.com/linode/manager/pull/9321)) +- MUI v5 Migration - `Components > Box` ([#9322](https://github.com/linode/manager/pull/9322)) +- MUI v5 Migration - `Components > CopyTooltip` ([#9323](https://github.com/linode/manager/pull/9323)) +- MUI v5 Migration - `Components > Button` ([#9325](https://github.com/linode/manager/pull/9325)) +- MUI v5 Migration - `Components > Hidden` ([#9326](https://github.com/linode/manager/pull/9326)) +- MUI v5 Migration - `Components > SelectionCard` ([#9327](https://github.com/linode/manager/pull/9327)) +- MUI v5 Migration - `Components > Typography` ([#9328](https://github.com/linode/manager/pull/9328)) +- MUI v5 Migration - `Components > Checkbox` (part 2) ([#9338](https://github.com/linode/manager/pull/9338)) +- MUI v5 Migration - `Components > Chip` ([#9339](https://github.com/linode/manager/pull/9339)) +- MUI v5 Migration - `Components > Snackbar` ([#9359](https://github.com/linode/manager/pull/9359)) +- MUI v5 Migration - `Components > Tooltip` ([#9369](https://github.com/linode/manager/pull/9369)) +- MUI v5 Migration - `Components > MenuItem` ([#9295](https://github.com/linode/manager/pull/9295)) +- MUI v5 Migration - `Components > Divider` ([#9353](https://github.com/linode/manager/pull/9353)) +- Remove old changelog scripting ([#9340](https://github.com/linode/manager/pull/9340)) +- Remove `withLoadingAndError` and clean up 2FA components ([#9318](https://github.com/linode/manager/pull/9318)) +- Link component: remove default export and improved Storybook story ([#9313](https://github.com/linode/manager/pull/9313)) +- Refactor components to use TypeToConfirmDialog ([#9175](https://github.com/linode/manager/pull/9175)) + ## [2023-06-29] - v1.96.2 ### Fixed: diff --git a/packages/manager/config/env.js b/packages/manager/config/env.js deleted file mode 100644 index f5b83ead49d..00000000000 --- a/packages/manager/config/env.js +++ /dev/null @@ -1,93 +0,0 @@ -'use strict'; - -const fs = require('fs'); -const path = require('path'); -const paths = require('./paths'); - -// Make sure that including paths.js after env.js will read .env variables. -delete require.cache[require.resolve('./paths')]; - -const NODE_ENV = process.env.NODE_ENV; -if (!NODE_ENV) { - throw new Error( - 'The NODE_ENV environment variable is required but was not specified.' - ); -} - -// https://github.com/bkeepers/dotenv#what-other-env-files-can-i-use -const dotenvFiles = [ - `${paths.dotenv}.${NODE_ENV}.local`, - `${paths.dotenv}.${NODE_ENV}`, - // Don't include `.env.local` for `test` environment - // since normally you expect tests to produce the same - // results for everyone - NODE_ENV !== 'test' && `${paths.dotenv}.local`, - paths.dotenv, -].filter(Boolean); - -// Load environment variables from .env* files. Suppress warnings using silent -// if this file is missing. dotenv will never modify any environment variables -// that have already been set. -// https://github.com/motdotla/dotenv -dotenvFiles.forEach((dotenvFile) => { - if (fs.existsSync(dotenvFile)) { - require('dotenv').config({ - path: dotenvFile, - }); - } -}); - -// We support resolving modules according to `NODE_PATH`. -// This lets you use absolute paths in imports inside large monorepos: -// https://github.com/facebookincubator/create-react-app/issues/253. -// It works similar to `NODE_PATH` in Node itself: -// https://nodejs.org/api/modules.html#modules_loading_from_the_global_folders -// Note that unlike in Node, only *relative* paths from `NODE_PATH` are honored. -// Otherwise, we risk importing Node.js core modules into an app instead of Webpack shims. -// https://github.com/facebookincubator/create-react-app/issues/1023#issuecomment-265344421 -// We also resolve them to make sure all tools using them work consistently. -const appDirectory = fs.realpathSync(process.cwd()); -process.env.NODE_PATH = (process.env.NODE_PATH || '') - .split(path.delimiter) - .filter((folder) => folder && !path.isAbsolute(folder)) - .map((folder) => path.resolve(appDirectory, folder)) - .join(path.delimiter); - -// Grab NODE_ENV and REACT_APP_* environment variables and prepare them to be -// injected into the application via DefinePlugin in Webpack configuration. -const REACT_APP = /^REACT_APP_/i; -function getClientEnvironment(publicUrl) { - const raw = Object.keys(process.env) - .filter((key) => REACT_APP.test(key)) - .reduce( - (env, key) => { - env[key] = process.env[key]; - return env; - }, - { - // Useful for determining whether we’re running in production mode. - // Most importantly, it switches React into the correct mode. - NODE_ENV: process.env.NODE_ENV || 'development', - // Useful for resolving the correct path to static assets in `public`. - // For example, . - // This should only be used as an escape hatch. Normally you would put - // images into the `src` and `import` them in code to get their paths. - PUBLIC_URL: publicUrl, - VERSION: paths.appVersion, - // Allow New Relic to be disabled when building Cloud Manager for - // environments where it is unneeded. - DISABLE_NEW_RELIC: process.env.DISABLE_NEW_RELIC, - } - ); - // Stringify all values so we can feed into Webpack DefinePlugin - const stringified = { - 'process.env': Object.keys(raw).reduce((env, key) => { - env[key] = JSON.stringify(raw[key]); - return env; - }, {}), - }; - - return { raw, stringified }; -} - -module.exports = getClientEnvironment; diff --git a/packages/manager/config/paths.js b/packages/manager/config/paths.js deleted file mode 100644 index 37acf94b481..00000000000 --- a/packages/manager/config/paths.js +++ /dev/null @@ -1,66 +0,0 @@ -'use strict'; - -const path = require('path'); -const fs = require('fs'); -const url = require('url'); - -// Make sure any symlinks in the project folder are resolved: -// https://github.com/facebookincubator/create-react-app/issues/637 -const appDirectory = fs.realpathSync(process.cwd()); -const resolveApp = (relativePath) => path.resolve(appDirectory, relativePath); - -const envPublicUrl = process.env.PUBLIC_URL; - -const envAppVersion = process.env.VERSION; - -function ensureSlash(pathVar, needsSlash) { - const hasSlash = pathVar.endsWith('/'); - if (hasSlash && !needsSlash) { - return pathVar.substr(pathVar, pathVar.length - 1); - } else if (!hasSlash && needsSlash) { - return `${pathVar}/`; - } else { - return pathVar; - } -} - -const getPublicUrl = (appPackageJson) => - envPublicUrl || require(appPackageJson).homepage; - -const getAppVersion = (appPackageJson) => - envAppVersion || require(appPackageJson).version; - -// We use `PUBLIC_URL` environment variable or "homepage" field to infer -// "public path" at which the app is served. -// Webpack needs to know it to put the right