diff --git a/.github/CONTRIBUTING.MD b/.github/CONTRIBUTING.MD index 4494c44cd2..1f64cf995d 100644 --- a/.github/CONTRIBUTING.MD +++ b/.github/CONTRIBUTING.MD @@ -2,26 +2,31 @@ ## Prerequisites -Before contributing to `carbon-addons-iot-react`, you should make sure you have the following tools -installed: +Before contributing to `carbon-addons-iot-react`, you should make sure you have +the following tools installed: -- [Node.js](https://nodejs.org/en/download/) - the required version is specified in the [`.nvmrc`](/.nvmrc) - - If you're on macOS or using WSL on Windows, we recommend using [`nvm`](https://github.com/nvm-sh/nvm) as your version manager for Node. +- [Node.js](https://nodejs.org/en/download/) - the required version is specified + in the [`.nvmrc`](/.nvmrc) + - If you're on macOS or using WSL on Windows, we recommend using + [`nvm`](https://github.com/nvm-sh/nvm) as your version manager for Node. - Git - [Yarn Classic](https://classic.yarnpkg.com/en/docs/install) -You'll also need a code editor to make changes. There are many to -choose from but some popular options are -[VSCode](https://code.visualstudio.com/), [Atom](https://atom.io), and -[Sublime](https://www.sublimetext.com/). +You'll also need a code editor to make changes. There are many to choose from +but some popular options are [VSCode](https://code.visualstudio.com/), +[Atom](https://atom.io), and [Sublime](https://www.sublimetext.com/). With that all in place, you're ready to start contributing! ### Developing on Windows 10 -To get a Windows environment set up for contributing to this codebase, you'll need to set up the Windows Subsystem for Linux (WSL). +To get a Windows environment set up for contributing to this codebase, you'll +need to set up the Windows Subsystem for Linux (WSL). -To set up WSL, follow [this guide published by the Carbon team](https://github.com/carbon-design-system/carbon/blob/master/docs/guides/setup/windows.md). The steps should be the same, except that you'll be cloning this repository instead of the Carbon repository. +To set up WSL, follow +[this guide published by the Carbon team](https://github.com/carbon-design-system/carbon/blob/master/docs/guides/setup/windows.md). +The steps should be the same, except that you'll be cloning this repository +instead of the Carbon repository. ```sh git clone git@github.com:carbon-design-system/carbon-addons-iot-react.git @@ -48,80 +53,132 @@ To get your development server running and to start coding, run: yarn start ``` -This will start a development server where you can see any changes you are making to components in our react components Storybook. +This will start a development server where you can see any changes you are +making to components in our react components Storybook. -Once it's done building, you can edit source code or create new components. The system is set up to automatically bundle your changes/additions. Visit http://localhost:3000 to see the changes happen on the fly. +Once it's done building, you can edit source code or create new components. The +system is set up to automatically bundle your changes/additions. Visit +http://localhost:3000 to see the changes happen on the fly. ## Adding a new component or feature -You're ready to add a new component or feature to this library, THANK YOU! However, this is only a [_presentational_](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) component library. Please do not add components with any dependencies on internationalization libraries, redux, react-router, etc. +You're ready to add a new component or feature to this library, THANK YOU! +However, this is only a +[_presentational_](https://medium.com/@dan_abramov/smart-and-dumb-components-7ca2f9a7c7d0) +component library. Please do not add components with any dependencies on +internationalization libraries, redux, react-router, etc. -For a component request or feature enhancement to be considered ‘ready to implement’, a design spec and usage guidance should be provided in the issue. Associated code pull requests will not be merged without these artifacts. +For a component request or feature enhancement to be considered ‘ready to +implement’, a design spec and usage guidance should be provided in the issue. +Associated code pull requests will not be merged without these artifacts. ## Dependencies -Dependencies must be added via `yarn add `. Please do not use `npm install `. +Dependencies must be added via `yarn add `. Please do not use +`npm install `. -When adding new `dependencies` or `devDependencies` to the codebase, the associated pull request should include justification for the package and the alternatives considered. +When adding new `dependencies` or `devDependencies` to the codebase, the +associated pull request should include justification for the package and the +alternatives considered. -Any change to `dependencies` (including version bumps) will impact consumers that are required to go through open source approvals within their organization. This approval process is not always a trivial task. `devDependencies` are less of a concern as they are not included in the exported package. +Any change to `dependencies` (including version bumps) will impact consumers +that are required to go through open source approvals within their organization. +This approval process is not always a trivial task. `devDependencies` are less +of a concern as they are not included in the exported package. ## Submitting pull requests and commits -Commits must follow the [conventional commit](https://www.conventionalcommits.org/en/v1.0.0-beta.2/#summary) format. You won't be able to create a commit unless you follow those rules. The [recent commits in the repository](https://github.com/carbon-design-system/carbon-addons-iot-react/commits/master) show examples of the format and how it's generally used. +All new development work should take place in a feature branch off of `next`. -For more information on what type of change commit should be labeled a `BREAKING CHANGE`, `feat`, or `fix`, please read [the versioning documentation](https://github.com/carbon-design-system/carbon-addons-iot-react/blob/master/docs/guides/versioning.md). +Commits must follow the +[conventional commit](https://www.conventionalcommits.org/en/v1.0.0-beta.2/#summary) +format. You won't be able to create a commit unless you follow those rules. The +[recent commits in the repository](https://github.com/carbon-design-system/carbon-addons-iot-react/commits/master) +show examples of the format and how it's generally used. -Commits are preferred but not required to contain a link to an issue. If you choose to link commits to an issue, the 72 character limit can be avoided by placing the link in the body of the commit. Example: +For more information on what type of change commit should be labeled a +`BREAKING CHANGE`, `feat`, or `fix`, please read +[the versioning documentation](https://github.com/carbon-design-system/carbon-addons-iot-react/blob/master/docs/guides/versioning.md). + +Commits are preferred but not required to contain a link to an issue. If you +choose to link commits to an issue, the 72 character limit can be avoided by +placing the link in the body of the commit. Example: ```sh git commit -m "fix(table): columns need unique ids" -m "#123" ``` -Pull requests must contain a link to a relevant issue. If applicable, [automatically close issues from PRs via the keywords](https://help.github.com/en/articles/closing-issues-using-keywords). +Pull requests must contain a link to a relevant issue. If applicable, +[automatically close issues from PRs via the keywords](https://help.github.com/en/articles/closing-issues-using-keywords). ## Styling new components -Components should have their own sass partial in which the corresponding styles are contained. If a component does not have one, please add it. +Components should have their own sass partial in which the corresponding styles +are contained. If a component does not have one, please add it. -Do not use `styled-components`. Any components using it should be refactored to the sass partial approach. This helps promote consistency with the Carbon Design System. +Do not use `styled-components`. Any components using it should be refactored to +the sass partial approach. This helps promote consistency with the Carbon Design +System. ## Testing An automated unit test bucket runs when you execute `yarn test:base`. -Before every push, the test suite is ran automatically and takes snapshots of all of the current component stories. If you have made changes to a component, our tests will likely fail because the snapshots will no longer match. You will be prevented from pushing to git until you fix this error. +Before every push, the test suite is ran automatically and takes snapshots of +all of the current component stories. If you have made changes to a component, +our tests will likely fail because the snapshots will no longer match. You will +be prevented from pushing to git until you fix this error. ### Writing tests The items below are high level points of guidance for writing tests: -- Use the `@testing-library` family of packages instead of `enzyme`. Helping to refactor away from `enzyme` where possible is appreciated. -- Prefer queries that reflect the experience of visual/mouse users as well as those that use assistive technology, [read more from the `@testing-library` docs](https://testing-library.com/docs/guide-which-query) - - `getByRole`, `getByLabelText`, `getByPlaceholderText`, `getByText`, `getByDisplayValue` -- Write tests using queries directly from the `screen` object rather than destructuring them from `render` result, [read more from the `prefer-screen-queries` eslint rule](https://github.com/testing-library/eslint-plugin-testing-library/blob/master/docs/rules/prefer-screen-queries.md) +- Use the `@testing-library` family of packages instead of `enzyme`. Helping to + refactor away from `enzyme` where possible is appreciated. +- Prefer queries that reflect the experience of visual/mouse users as well as + those that use assistive technology, + [read more from the `@testing-library` docs](https://testing-library.com/docs/guide-which-query) + - `getByRole`, `getByLabelText`, `getByPlaceholderText`, `getByText`, + `getByDisplayValue` +- Write tests using queries directly from the `screen` object rather than + destructuring them from `render` result, + [read more from the `prefer-screen-queries` eslint rule](https://github.com/testing-library/eslint-plugin-testing-library/blob/master/docs/rules/prefer-screen-queries.md) ### Updating snapshots -After the unit test engine has detected a snapshot difference, all snapshots can be updated by running `yarn test:update`. +After the unit test engine has detected a snapshot difference, all snapshots can +be updated by running `yarn test:update`. -_Do not blindly update snapshots to pass the testcase._ Make sure the detected change is intentional and not unintentional before updating the snapshot. +_Do not blindly update snapshots to pass the testcase._ Make sure the detected +change is intentional and not unintentional before updating the snapshot. ### Minimum code coverage -Code coverage thresholds are enforced in the repository. If you add code but do not cover it with unit tests, the git push may fail because the coverage fell to a level under the required code coverage thresholds. Please add storybook stories or unit tests to cover your new code before checking in. _Do not reduce the code coverage threshold to get around this constraint._ +Code coverage thresholds are enforced in the repository. If you add code but do +not cover it with unit tests, the git push may fail because the coverage fell to +a level under the required code coverage thresholds. Please add storybook +stories or unit tests to cover your new code before checking in. _Do not reduce +the code coverage threshold to get around this constraint._ -To understand what lines of code are NOT covered by the current testcases, open the coverage/index.html file in a browser and investigate. +To understand what lines of code are NOT covered by the current testcases, open +the coverage/index.html file in a browser and investigate. ## Setting up VSCode to share settings and extensions -Some contributors to this repository are using some pretty cool VSCode extensions to make local development easier. If you'd like to reuse the same ones, follow [the instructions to set up the VSCode Settings Sync](http://shanalikhan.github.io/2015/12/15/Visual-Studio-Code-Sync-Settings.html). +Some contributors to this repository are using some pretty cool VSCode +extensions to make local development easier. If you'd like to reuse the same +ones, follow +[the instructions to set up the VSCode Settings Sync](http://shanalikhan.github.io/2015/12/15/Visual-Studio-Code-Sync-Settings.html). -Here's the Gist ID to download/share settings from: `5e3fb697c29f2aaa058145a3349a8229` +Here's the Gist ID to download/share settings from: +`5e3fb697c29f2aaa058145a3349a8229` -After installing the VSCode Sync, restart VSCode, go to the Command Palette and search for Sync. Select Sync : Advanced Options-> Sync : Download Settings from Public GIST +After installing the VSCode Sync, restart VSCode, go to the Command Palette and +search for Sync. Select Sync : Advanced Options-> Sync : Download Settings from +Public GIST -Then Sync : Download Settings. It will ask you for a Public GIST URL, here it is. +Then Sync : Download Settings. It will ask you for a Public GIST URL, here it +is. Here's the Public GIST URL: https://gist.github.com/scottdickerson/5e3fb697c29f2aaa058145a3349a8229 diff --git a/README.MD b/README.MD index 3d45722f90..9de6227d0c 100644 --- a/README.MD +++ b/README.MD @@ -1,5 +1,5 @@

- + Carbon add-ons for Watson IoT

@@ -13,21 +13,15 @@ > and a vibrant community of contributors.

- - Our Storybook + + @latest npm version release - - Netlify status + + @next npm version release Build Status - - Current npm version release - - - Next npm version release - Coverage Report @@ -41,53 +35,64 @@ ## Installation -Run the following command using [npm](https://www.npmjs.com/): +**@latest from +[`master`](https://github.com/carbon-design-system/carbon-addons-iot-react/tree/master)** +  -   +view @latest storybook + -```bash -npm install carbon-addons-iot-react d3@">=5.0.0 <=5.14.2" ``` +# with npm +npm install carbon-addons-iot-react d3@">=5.0.0 <=5.14.2" -If you prefer [Yarn Classic](https://classic.yarnpkg.com/), use the following -command instead: - -```bash +# with yarn yarn add carbon-addons-iot-react d3@">=5.0.0 <=5.14.2" ``` -> _Note `d3` is a peer dependency due to the usage of `@carbon/charts` in -> various components. The required version range is specified in -> [our package.json](https://github.com/carbon-design-system/carbon-addons-iot-react/search?l=JSON&q=peerDependencies+d3)_ +**@next pre-releases from +[`next`](https://github.com/carbon-design-system/carbon-addons-iot-react/tree/next)** +  -   +view @next storybook + -You can then import any component that you need by doing the following in your -project: +``` +# with npm +npm install carbon-addons-iot-react@next d3@">=5.0.0 <=5.14.2" -```js -import { AddCard } from 'carbon-addons-iot-react'; +# with yarn +yarn add carbon-addons-iot-react@next d3@">=5.0.0 <=5.14.2" ``` -Prerelease versions are available on `carbon-addons-iot-react@next`. The semver -range in your project's `package.json` can be modified to follow the `next` -channel: +> _`d3` is a peer dependency due to the usage of `@carbon/charts` in various +> components. The required version range is specified in +> [package.json](https://github.com/carbon-design-system/carbon-addons-iot-react/search?l=JSON&q=peerDependencies+d3)_ -``` +### Subscribe to all pre-releases on `next` + +[Pre-release versions](https://semver.org/#spec-item-9) are available on +`carbon-addons-iot-react@next`. The default version range that is automatically +added to your `package.json` on install/add will only follow pre-releases on the +same `major.minor.patch` version. The version range can be modifed to follow all +pre-releases: + +```diff "dependencies": { - "carbon-addons-iot-react": "next", -} +- "carbon-addons-iot-react": "^2.139.0-next.4" ++ "carbon-addons-iot-react": "next" + } ``` ## 🚀 Quick Start -If you'd like to test drive everything here, run the following command to create -a new project preconfigured with everything you need to begin to build an -application. +To test drive everything here, use +[`create-iot-react-app`](https://github.com/davidicus/create-iot-react-app). It +will create a new project that is preconfigured with everything you need to +begin to build an application. -```sh +``` npx create-iot-react-app ``` -More -[info on `create-iot-react-app` here](https://github.com/davidicus/create-iot-react-app) - ## Styling What's included @@ -130,11 +135,6 @@ packages; `carbon-components`, `carbon-components-react`, or `@carbon` packages (`@carbon/grid`, `@carbon-layout`, etc) as peer dependencies. You may still need these packages if you use them directly in your project. -## 📚 Docs - -You can find more information about how to use each component by checking out -the [Storybook](https://carbon-addons-iot-react.com/). - ## 🤲 Contributing Please check out our [Contribution Guidelines](./.github/CONTRIBUTING.MD) for diff --git a/docs/guides/versioning.md b/docs/guides/versioning.md index 8e632c847c..344622260a 100644 --- a/docs/guides/versioning.md +++ b/docs/guides/versioning.md @@ -23,14 +23,21 @@ As a result, whenever you see a `minor` or `patch` update for a package from `carbon-addons-iot-react` you should feel confident that you can update without anything breaking in your project. -Prerelease versions are available on `carbon-addons-iot-react@next`. The semver -range in your project's `package.json` can be modified to follow the `next` -channel: +All new development takes place on the `next` branch. For every PR that is +merged, a new release is published to the `@next` channel. Periodically, the +`next` branch is merged into `master` triggering a release on `@latest`. -``` +[Pre-release versions](https://semver.org/#spec-item-9) are available on +`carbon-addons-iot-react@next`. The default version range that is automatically +added to your `package.json` on install/add will only follow pre-releases on the +same `major.minor.patch` version. The version range can be modifed to follow all +pre-releases: + +```diff "dependencies": { - "carbon-addons-iot-react": "next", -} +- "carbon-addons-iot-react": "^2.139.0-next.4" ++ "carbon-addons-iot-react": "next" + } ``` **Note:** If you ever bring in an update and it does break something in your diff --git a/jest.config.js b/jest.config.js index 55d1e13855..0a76eec30b 100644 --- a/jest.config.js +++ b/jest.config.js @@ -13,12 +13,17 @@ module.exports = { functions: 80, lines: 80, }, - './src/components/**/!(ColumnHeaderSelect|FilterHeaderRow|TableToolbar|RowActionsCell|RowActionsError|StatefulTable|StatefulTableDetailWizard|CatalogContent|FileDrop|HeaderMenu|Dashboard|CardRenderer|Attribute|UnitRenderer|ImageHotspots|ImageControls|PageHero|PageTitle|EditPage|AsyncTable|ImageCard|WizardHeader|TableHead|ColumnResize|DateTimePicker|TimeSeriesCard|BarChartCard).jsx': { + './src/components/**/!(ColumnHeaderSelect|FilterHeaderRow|TableToolbar|RowActionsCell|RowActionsError|StatefulTable|StatefulTableDetailWizard|CatalogContent|FileDrop|HeaderMenu|Dashboard|CardRenderer|Attribute|UnitRenderer|ImageHotspots|ImageControls|PageHero|PageTitle|EditPage|AsyncTable|ImageCard|WizardHeader|TableHead|ColumnResize|DateTimePicker|TimeSeriesCard|BarChartCard|DashboardGrid).jsx': { statements: 80, branches: 80, functions: 80, lines: 80, }, + './src/components/Dashboard/DashboardGrid.jsx': { + statements: 73, + branches: 61, + lines: 73, + }, './src/components/BarChartCard/BarChartCard.jsx': { // TODO: Add tests for tooltip interaction and formatting when below issue is solved // https://github.com/carbon-design-system/carbon-charts/issues/594 diff --git a/package.json b/package.json index 384422803e..5ae0c661c8 100644 --- a/package.json +++ b/package.json @@ -136,7 +136,6 @@ "carbon-components": "10.17.0", "carbon-components-react": "7.17.0", "carbon-icons": "^7.0.7", - "cheerio": "^1.0.0-rc.3", "classnames": "^2.2.5", "core-js": "3.6.5", "downshift": "5.2.1", @@ -153,7 +152,6 @@ "react-sizeme": "^2.6.3", "react-transition-group": "^2.6.0", "react-visibility-sensor": "^5.0.2", - "rollup-plugin-auto-external": "^2.0.0", "styled-components": "^4.1.3", "use-deep-compare-effect": "^1.2.0", "use-lang-direction": "^0.1.11", @@ -265,8 +263,6 @@ "rollup-plugin-copy": "^3.2.0", "rollup-plugin-filesize": "^6.0.0", "rollup-plugin-json": "^4.0.0", - "rollup-plugin-node-builtins": "^2.1.2", - "rollup-plugin-node-globals": "^1.4.0", "rollup-plugin-node-resolve": "^4.0.0", "rollup-plugin-postcss": "^2.0.3", "rollup-plugin-replace": "^2.1.0", diff --git a/rollup.config.js b/rollup.config.js index 10b325aa6c..ba9998d238 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -8,7 +8,6 @@ import postcss from 'rollup-plugin-postcss'; import copy from 'rollup-plugin-copy'; import autoprefixer from 'autoprefixer'; import json from 'rollup-plugin-json'; -import builtins from 'rollup-plugin-node-builtins'; import svgr from '@svgr/rollup'; const packageJson = require('./package.json'); @@ -30,51 +29,6 @@ const external = (id) => { id.includes('@babel/runtime') ); }; -const plugins = [ - resolve({ mainFields: ['module', 'main'], extensions, preferBuiltins: true }), - builtins(), - commonjs({ - namedExports: { - 'react/index.js': [ - 'Children', - 'Component', - 'PureComponent', - 'Fragment', - 'PropTypes', - 'createElement', - ], - 'react-dom/index.js': ['render'], - 'react-is/index.js': ['isForwardRef'], - 'core-js': 'CoreJs', - }, - - include: '/node_modules/', - }), - - babel({ - exclude: 'node_modules/**', - runtimeHelpers: true, - }), - replace({ - 'process.env.NODE_ENV': JSON.stringify(env), - }), - json({ - // All JSON files will be parsed by default, - // but you can also specifically include/exclude files - exclude: ['node_modules'], - // for tree-shaking, properties will be declared as - // variables, using either `var` or `const` - preferConst: true, // Default: false - // specify indentation for the generated default export — - // defaults to '\t' - indent: ' ', - // ignores indent and generates the smallest code - compact: true, // Default: false - // generate a named export for every property of the JSON object - namedExports: true, // Default: true - }), - svgr(), -]; export default [ // CommonJS & ESM @@ -93,7 +47,50 @@ export default [ }, ], external, - plugins: [...plugins, ...prodSettings], + plugins: [ + resolve({ mainFields: ['module', 'main'], extensions }), + commonjs({ + namedExports: { + 'react/index.js': [ + 'Children', + 'Component', + 'PureComponent', + 'Fragment', + 'PropTypes', + 'createElement', + ], + 'react-dom/index.js': ['render'], + 'react-is/index.js': ['isForwardRef'], + 'core-js': 'CoreJs', + }, + + include: '/node_modules/', + }), + babel({ + exclude: 'node_modules/**', + runtimeHelpers: true, + }), + replace({ + 'process.env.NODE_ENV': JSON.stringify(env), + }), + json({ + // All JSON files will be parsed by default, + // but you can also specifically include/exclude files + exclude: ['node_modules'], + // for tree-shaking, properties will be declared as + // variables, using either `var` or `const` + preferConst: true, // Default: false + // specify indentation for the generated default export — + // defaults to '\t' + indent: ' ', + // ignores indent and generates the smallest code + compact: true, // Default: false + // generate a named export for every property of the JSON object + namedExports: true, // Default: true + }), + svgr(), + ...prodSettings, + ], }, // Compile styles { @@ -149,10 +146,8 @@ export default [ plugins: [ resolve({ browser: true, - extensions: ['.mjs', '.js', '.jsx', '.json'], - preferBuiltins: true, + extensions, }), - builtins(), commonjs({ namedExports: { 'react-js': ['isValidElementType'], diff --git a/src/components/BarChartCard/BarChartCard.jsx b/src/components/BarChartCard/BarChartCard.jsx index bcea2ea7d5..67b4f8520e 100644 --- a/src/components/BarChartCard/BarChartCard.jsx +++ b/src/components/BarChartCard/BarChartCard.jsx @@ -20,6 +20,7 @@ import Card from '../Card/Card'; import { settings } from '../../constants/Settings'; import { chartValueFormatter, + getResizeHandles, handleCardVariables, increaseSmallCardSize, } from '../../utils/cardUtilityFunctions'; @@ -43,6 +44,7 @@ const memoizedGenerateSampleValues = memoize(generateSampleValues); const BarChartCard = ({ title: titleProp, content, + children, size: sizeProp, values: initialValues, locale, @@ -51,6 +53,7 @@ const BarChartCard = ({ isLazyLoading, isEditable, isLoading, + isResizable, interval, className, domainRange, @@ -77,6 +80,8 @@ const BarChartCard = ({ const size = increaseSmallCardSize(sizeProp, 'BarChartCard'); + const resizeHandles = isResizable ? getResizeHandles(children) : []; + // If editable, show sample presentation data // If there is no series defined, there is no datasets to make sample data from const values = @@ -159,6 +164,8 @@ const BarChartCard = ({ isLazyLoading={isLazyLoading} isEditable={isEditable} isLoading={isLoading} + isResizable={isResizable} + resizeHandles={resizeHandles} {...others}> {!isAllValuesEmpty ? (

{ const colors = { identifier: 'group', scale: {} }; // if color is an array, order doesn't matter so just map as many as possible - if (Array.isArray(series[0].color)) { + if (series[0] && Array.isArray(series[0].color)) { series[0].color.forEach((color, index) => { colors.scale[datasetNames[index]] = color; }); @@ -335,7 +335,7 @@ export const handleTooltip = ( : dataOrHoveredElement; const typedData = Array.isArray(data) ? data[0] : data; - const parsedTooltip = cheerio.load(defaultTooltip); + const [parsedTooltip] = convertStringsToDOMElement([defaultTooltip]); // If theres a time attribute, add an extra list item with the formatted date if (timeDataSourceId) { @@ -351,12 +351,16 @@ export const handleTooltip = ( ` : ''; + const [parsedDateLabel] = convertStringsToDOMElement([dateLabel]); + // First remove carbon charts default Date tooltip - // the first
  • will always be carbon chart's Dates row in this case - parsedTooltip('li:first-child').replaceWith(dateLabel); + // the first
  • will always be carbon chart's Dates row in this case, replace with our date format
  • + parsedTooltip + .querySelector('li:first-child') + .replaceWith(parsedDateLabel.querySelector('li')); } - return parsedTooltip.html('ul'); + return parsedTooltip.innerHTML; }; /** diff --git a/src/components/Card/Card.jsx b/src/components/Card/Card.jsx index f7f144703d..25949ff03f 100644 --- a/src/components/Card/Card.jsx +++ b/src/components/Card/Card.jsx @@ -22,7 +22,10 @@ import { getCardMinSize, filterValidAttributes, } from '../../utils/componentUtilityFunctions'; -import { getUpdatedCardSize } from '../../utils/cardUtilityFunctions'; +import { + getUpdatedCardSize, + useCardResizing, +} from '../../utils/cardUtilityFunctions'; import CardToolbar from './CardToolbar'; @@ -264,6 +267,8 @@ const Card = (props) => { isEditable, isExpanded, isLazyLoading, + isResizable, + resizeHandles: wrappingCardResizeHandles, error, hideHeader, id, @@ -344,6 +349,12 @@ const Card = (props) => { } }); + const { resizeHandles, isResizing } = useCardResizing( + wrappingCardResizeHandles, + children, + isResizable + ); + const card = ( {({ isVisible }) => ( @@ -379,7 +390,9 @@ const Card = (props) => { width: 'calc(100% - 50px)', } } - className={classnames(`${iotPrefix}--card`, className)}> + className={classnames(`${iotPrefix}--card`, className, { + [`${iotPrefix}--card--resizing`]: isResizing, + })}> {!hideHeader && ( @@ -451,6 +464,7 @@ const Card = (props) => { children )} + {resizeHandles} ); }} diff --git a/src/components/Card/_card.scss b/src/components/Card/_card.scss index 06b45d16c9..e4dcaa04a9 100644 --- a/src/components/Card/_card.scss +++ b/src/components/Card/_card.scss @@ -20,6 +20,12 @@ $iot-header-padding: $spacing-05; } } +.#{$iot-prefix}--card--resizing { + border: $spacing-01 solid $interactive-02; + box-sizing: content-box; + margin: -$spacing-01; +} + .#{$iot-prefix}--card--title { flex: 1; // min-width value is required to ensure flex child with text properly truncates diff --git a/src/components/CardEditor/CardEditForm/CardEditForm.jsx b/src/components/CardEditor/CardEditForm/CardEditForm.jsx index 2143719b22..ad69618be1 100644 --- a/src/components/CardEditor/CardEditForm/CardEditForm.jsx +++ b/src/components/CardEditor/CardEditForm/CardEditForm.jsx @@ -3,22 +3,14 @@ import PropTypes from 'prop-types'; import { Code16 } from '@carbon/icons-react'; import isEmpty from 'lodash/isEmpty'; -import { - CARD_SIZES, - CARD_DIMENSIONS, - ALLOWED_CARD_SIZES_PER_TYPE, -} from '../../../constants/LayoutConstants'; +import { CARD_DIMENSIONS } from '../../../constants/LayoutConstants'; import { settings } from '../../../constants/Settings'; -import { - Tabs, - Tab, - Button, - TextArea, - TextInput, - Dropdown, -} from '../../../index'; +import { Tabs, Tab, Button } from '../../../index'; import CardCodeEditor from '../../CardCodeEditor/CardCodeEditor'; +import CardEditFormContent from './CardEditFormContent'; +import CardEditFormSettings from './CardEditFormSettings'; + const { iotPrefix } = settings; const propTypes = { @@ -26,14 +18,40 @@ const propTypes = { cardJson: PropTypes.object, // eslint-disable-line react/forbid-prop-types /** Callback function when form data changes */ onChange: PropTypes.func.isRequired, + i18n: PropTypes.shape({ + openEditorButton: PropTypes.string, + contentTabLabel: PropTypes.string, + settingsTabLabel: PropTypes.string, + cardSize_SMALL: PropTypes.string, + cardSize_SMALLWIDE: PropTypes.string, + cardSize_MEDIUM: PropTypes.string, + cardSize_MEDIUMTHIN: PropTypes.string, + cardSize_MEDIUMWIDE: PropTypes.string, + cardSize_LARGE: PropTypes.string, + cardSize_LARGETHIN: PropTypes.string, + cardSize_LARGEWIDE: PropTypes.string, + chartType_BAR: PropTypes.string, + chartType_LINE: PropTypes.string, + barChartType_SIMPLE: PropTypes.string, + barChartType_GROUPED: PropTypes.string, + barChartType_STACKED: PropTypes.string, + barChartLayout_HORIZONTAL: PropTypes.string, + barChartLayout_VERTICAL: PropTypes.string, + }), + /** if provided, returns an array of strings which are the dataItems to be allowed + * on each card + * getValidDataItems(card, selectedTimeRange) + */ + getValidDataItems: PropTypes.func, + /** an array of dataItem string names to be included on each card + * this prop will be ignored if getValidDataItems is defined + */ + dataItems: PropTypes.arrayOf(PropTypes.string), /** If provided, runs the function when the user clicks submit in the Card code JSON editor * onValidateCardJson(cardJson) * @returns Array error strings. return empty array if there is no errors */ onValidateCardJson: PropTypes.func, - i18n: PropTypes.shape({ - openEditorButton: PropTypes.string, - }), }; const defaultProps = { @@ -41,6 +59,7 @@ const defaultProps = { i18n: { openEditorButton: 'Open JSON editor', contentTabLabel: 'Content', + settingsTabLabel: 'Settings', cardSize_SMALL: 'Small', cardSize_SMALLWIDE: 'Small wide', cardSize_MEDIUM: 'Medium', @@ -58,6 +77,8 @@ const defaultProps = { barChartLayout_VERTICAL: 'Vertical', // additional card type names can be provided using the convention of `cardType_TYPE` }, + getValidDataItems: null, + dataItems: [], onValidateCardJson: null, }; @@ -126,64 +147,20 @@ export const handleSubmit = ( return false; }; -const CardEditForm = ({ cardJson, onChange, onValidateCardJson, i18n }) => { +const CardEditForm = ({ + cardJson, + onChange, + i18n, + dataItems, + onValidateCardJson, + getValidDataItems, +}) => { const mergedI18n = { ...defaultProps.i18n, ...i18n }; const [showEditor, setShowEditor] = useState(false); const [modalData, setModalData] = useState(); const baseClassName = `${iotPrefix}--card-edit-form`; - const commonFormItems = ( - <> -
    - onChange({ ...cardJson, title: evt.target.value })} - value={cardJson.title} - /> -
    -
    -