diff --git a/packages/react-core/src/demos/CardView/examples/CardView.md b/packages/react-core/src/demos/CardView/examples/CardView.md new file mode 100644 index 00000000000..04e12891f8b --- /dev/null +++ b/packages/react-core/src/demos/CardView/examples/CardView.md @@ -0,0 +1,769 @@ +--- +title: 'Card view' +section: 'demos' +experimentalStage: 'early' +--- + +import React from 'react'; +import { +Avatar, +Brand, +Button, +ButtonVariant, +Card, +CardHead, +CardActions, +CardHeader, +CardBody, +Checkbox, +Dropdown, +DropdownToggle, +DropdownItem, +DropdownSeparator, +DropdownPosition, +DropdownDirection, +Gallery, +GalleryItem, +KebabToggle, +Nav, +NavItem, +NavList, +NavVariants, +Page, +PageHeader, +PageSection, +PageSectionVariants, +PageSidebar, +SkipToContent, +TextContent, +Text, +Toolbar, +ToolbarGroup, +ToolbarItem +} from '@patternfly/react-core'; +import accessibleStyles from '@patternfly/react-styles/css/utilities/Accessibility/accessibility'; +import spacingStyles from '@patternfly/react-styles/css/utilities/Spacing/spacing'; +import { css } from '@patternfly/react-styles'; +import { BellIcon, CogIcon, FilterIcon, TrashIcon } from '@patternfly/react-icons'; +import imgBrand from '@patternfly/react-core/src/demos/PageLayout/examples/imgBrand.svg'; +import imgAvatar from '@patternfly/react-core/src/demos/PageLayout/examples/imgAvatar.svg'; +import pfIcon from './pf-logo-small.svg'; +import activeMQIcon from './activemq-core_200x150.png'; +import avroIcon from './camel-avro_200x150.png'; +import dropBoxIcon from './camel-dropbox_200x150.png'; +import infinispanIcon from './camel-infinispan_200x150.png'; +import saxonIcon from './camel-saxon_200x150.png'; +import sparkIcon from './camel-spark_200x150.png'; +import swaggerIcon from './camel-swagger-java_200x150.png'; +import azureIcon from './FuseConnector_Icons_AzureServices.png'; +import restIcon from './FuseConnector_Icons_REST.png'; + +This is a demo that showcases Patternfly cards. + +## Examples + +```js title=Basic isFullscreen +import React from 'react'; +import { + Avatar, + Brand, + Button, + ButtonVariant, + Card, + CardHead, + CardActions, + CardHeader, + CardBody, + Checkbox, + Dropdown, + DropdownToggle, + DropdownItem, + DropdownSeparator, + DropdownPosition, + DropdownDirection, + DropdownToggleCheckbox, + Gallery, + GalleryItem, + KebabToggle, + Nav, + NavItem, + NavList, + NavVariants, + Page, + PageHeader, + PageSection, + PageSectionVariants, + PageSidebar, + Pagination, + Select, + SelectOption, + SkipToContent, + TextContent, + Text, + Toolbar, + ToolbarGroup, + ToolbarItem +} from '@patternfly/react-core'; +import { + DataToolbar, + DataToolbarContent, + DataToolbarFilter, + DataToolbarToggleGroup, + DataToolbarGroup, + DataToolbarItem +} from '@patternfly/react-core/dist/esm/experimental'; +// make sure you've installed @patternfly/patternfly +import accessibleStyles from '@patternfly/react-styles/css/utilities/Accessibility/accessibility'; +import spacingStyles from '@patternfly/react-styles/css/utilities/Spacing/spacing'; +import { css } from '@patternfly/react-styles'; +import { BellIcon, CogIcon, FilterIcon, TrashIcon } from '@patternfly/react-icons'; +import imgBrand from '@patternfly/react-core/src/demos/PageLayout/examples/imgBrand.svg'; +import imgAvatar from '@patternfly/react-core/src/demos/PageLayout/examples/imgAvatar.svg'; +import pfIcon from './pf-logo-small.svg'; +import activeMQIcon from './activemq-core_200x150.png'; +import avroIcon from './camel-avro_200x150.png'; +import dropBoxIcon from './camel-dropbox_200x150.png'; +import infinispanIcon from './camel-infinispan_200x150.png'; +import saxonIcon from './camel-saxon_200x150.png'; +import sparkIcon from './camel-spark_200x150.png'; +import swaggerIcon from './camel-swagger-java_200x150.png'; +import azureIcon from './FuseConnector_Icons_AzureServices.png'; +import restIcon from './FuseConnector_Icons_REST.png'; + +class CardViewBasic extends React.Component { + constructor(props) { + super(props); + + this.handleCheckboxClick = this.handleCheckboxClick.bind(this); + + this.state = { + filters: { + products: [] + }, + res: [], + selectedItems: [], + areAllSelected: false, + itemsCheckedByDefault: false, + isUpperToolbarDropdownOpen: false, + isUpperToolbarKebabDropdownOpen: false, + isLowerToolbarDropdownOpen: false, + isLowerToolbarKebabDropdownOpen: false, + isCardKebabDropdownOpen: false, + activeItem: 0, + splitButtonDropdownIsOpen: false, + page: 1, + perPage: 10, + totalItemCount: 10 + }; + + this.onPageDropdownToggle = isUpperToolbarDropdownOpen => { + this.setState({ + isUpperToolbarDropdownOpen + }); + }; + + this.onPageDropdownSelect = event => { + this.setState({ + isUpperToolbarDropdownOpen: !this.state.isUpperToolbarDropdownOpen + }); + }; + + this.onPageToolbarDropdownToggle = isPageToolbarDropdownOpen => { + this.setState({ + isPageToolbarDropdownOpen + }); + }; + + this.onPageToolbarKebabDropdownToggle = isUpperToolbarKebabDropdownOpen => { + this.setState({ + isUpperToolbarKebabDropdownOpen + }); + }; + + this.onToolbarDropdownToggle = isLowerToolbarDropdownOpen => { + this.setState(prevState => ({ + isLowerToolbarDropdownOpen + })); + }; + + this.onToolbarDropdownSelect = event => { + this.setState({ + isLowerToolbarDropdownOpen: !this.state.isLowerToolbarDropdownOpen + }); + }; + + this.onToolbarKebabDropdownToggle = isLowerToolbarKebabDropdownOpen => { + this.setState({ + isLowerToolbarKebabDropdownOpen + }); + }; + + this.onToolbarKebabDropdownSelect = event => { + this.setState({ + isLowerToolbarKebabDropdownOpen: !this.state.isLowerToolbarKebabDropdownOpen + }); + }; + + this.onCardKebabDropdownToggle = (key, isCardKebabDropdownOpen) => { + this.setState({ + [key]: isCardKebabDropdownOpen + }); + }; + + this.onCardKebabDropdownSelect = (key, event) => { + this.setState({ + [key]: !this.state[key] + }); + }; + + this.onNavSelect = result => { + this.setState({ + activeItem: result.itemId + }); + }; + + this.deleteItem = item => event => { + const filter = getter => val => getter(val) !== item.id; + this.setState({ + res: this.state.res.filter(filter(({ id }) => id)), + selectedItems: this.state.selectedItems.filter(filter(id => id)) + }); + }; + + this.onSetPage = (_event, pageNumber) => { + this.setState({ + page: pageNumber + }); + }; + + this.onPerPageSelect = (_event, perPage) => { + this.setState({ + perPage + }); + }; + + this.onSplitButtonToggle = isOpen => { + this.setState({ + splitButtonDropdownIsOpen: isOpen + }); + }; + + this.onSplitButtonSelect = event => { + this.setState((prevState, props) => { + return { splitButtonDropdownIsOpen: !prevState.splitButtonDropdownIsOpen }; + }); + }; + + this.onNameSelect = (event, selection) => { + const checked = event.target.checked; + this.setState(prevState => { + const prevSelections = prevState.filters['products']; + return { + filters: { + ...prevState.filters, + ['products']: checked ? [...prevSelections, selection] : prevSelections.filter(value => value !== selection) + } + }; + }); + }; + + this.onDelete = (type = '', id = '') => { + if (type) { + this.setState(prevState => { + prevState.filters[type.toLowerCase()] = prevState.filters[type.toLowerCase()].filter(s => s !== id); + return { + filters: prevState.filters + }; + }); + } else { + this.setState({ + filters: { + products: [] + } + }); + } + }; + } + + selectedItems(e) { + const { value, checked } = e.target; + let { selectedItems } = this.state; + + if (checked) { + selectedItems = [...selectedItems, value]; + } else { + selectedItems = selectedItems.filter(el => el !== value); + if (this.state.areAllSelected) { + this.setState({ + areAllSelected: !this.state.areAllSelected + }); + } + } + this.setState({ selectedItems }); + } + + splitCheckboxSelectAll(e) { + const { checked } = e.target; + const { isChecked, res } = this.state; + let collection = []; + + if (checked) { + for (var i = 0; i <= 9; i++) collection = [...collection, i]; + } + + this.setState( + { + selectedItems: collection, + isChecked: isChecked, + areAllSelected: checked + }, + this.updateSelected + ); + } + + selectPage(e) { + const { checked } = e.target; + const { isChecked, totalItemCount, perPage } = this.state; + let collection = []; + + collection = this.getAllItems(); + + this.setState( + { + selectedItems: collection, + isChecked: checked, + areAllSelected: totalItemCount === perPage ? true : false + }, + this.updateSelected + ); + } + + selectAll(e) { + const { checked } = e.target; + const { isChecked } = this.state; + + let collection = []; + for (var i = 0; i <= 9; i++) collection = [...collection, i]; + + this.setState( + { + selectedItems: collection, + isChecked: true, + areAllSelected: true + }, + this.updateSelected + ); + } + + selectNone(e) { + const { checked } = e.target; + const { isChecked, selectedItems } = this.state; + this.setState( + { + selectedItems: [], + isChecked: false, + areAllSelected: false + }, + this.updateSelected + ); + } + + getAllItems() { + const { res } = this.state; + const collection = []; + for (const items of res) { + collection.push(items.id); + } + + return collection; + } + + handleCheckboxClick(checked, e) { + const { value } = e.target; + const { totalItemCount } = this.state; + + if (checked) { + const collection = this.getAllItems(); + this.setState(prevState => ({ + selectedItems: [...prevState.selectedItems, value * 1], + areAllSelected: totalItemCount === prevState.selectedItems.length + 1 + })); + } else { + this.setState(prevState => ({ + selectedItems: prevState.selectedItems.filter(item => item != value), + areAllSelected: false + })); + } + } + + updateSelected() { + const { res, selectedItems } = this.state; + let rows = res.map(post => { + post.selected = selectedItems.includes(post.id); + return post; + }); + + this.setState({ + res: rows + }); + } + + fetch(page, perPage) { + fetch(`https://my-json-server.typicode.com/jenny-s51/cardviewdata/posts?_page=${page}&_limit=${perPage}`) + .then(resp => resp.json()) + .then(resp => this.setState({ res: resp, perPage, page })) + .then(() => this.updateSelected()) + .catch(err => this.setState({ error: err })); + } + + componentDidMount() { + this.fetch(this.state.page, this.state.perPage); + } + + renderPagination() { + const { page, perPage, totalItemCount } = this.state; + + const defaultPerPageOptions = [ + { + title: '1', + value: 1 + }, + { + title: '5', + value: 5 + }, + { + title: '10', + value: 10 + } + ]; + + return ( + { + this.fetch(value, perPage); + }} + onPerPageSelect={(_evt, value) => { + this.fetch(1, value); + }} + variant="top" + /> + ); + } + + buildSelectDropdown() { + const { splitButtonDropdownIsOpen, selectedItems, areAllSelected } = this.state; + const numSelected = selectedItems.length; + const allSelected = areAllSelected; + const anySelected = numSelected > 0; + const someChecked = anySelected ? null : false; + const isChecked = allSelected ? true : someChecked; + const splitButtonDropdownItems = [ + + Select none (0 items) + , + + Select page ({this.state.perPage} items) + , + + Select all ({this.state.totalItemCount} items) + + ]; + + return ( + + ]} + onToggle={this.onSplitButtonToggle} + > + {numSelected !== 0 && {numSelected} selected} + + } + isOpen={splitButtonDropdownIsOpen} + dropdownItems={splitButtonDropdownItems} + /> + ); + } + + buildFilterDropdown() { + const { isLowerToolbarDropdownOpen, filters } = this.state; + + const filterDropdownItems = [ + , + , + , + , + , + , + , + , + , + + ]; + + return ( + + + + ); + } + + render() { + const { + isUpperToolbarDropdownOpen, + isLowerToolbarDropdownOpen, + isUpperToolbarKebabDropdownOpen, + isLowerToolbarKebabDropdownOpen, + isCardKebabDropdownOpen, + splitButtonDropdownIsOpen, + activeItem, + filters, + res, + checked, + selectedItems, + itemsCheckedByDefault, + areAllSelected, + isChecked + } = this.state; + + const toolbarKebabDropdownItems = [ + Link, + + Action + , + + Disabled Link + , + + Disabled Action + , + , + Separated Link, + + Separated Action + + ]; + + const toolbarItems = ( + + {this.buildSelectDropdown()} + {this.buildFilterDropdown()} + + + + + } + isOpen={isLowerToolbarKebabDropdownOpen} + isPlain + dropdownItems={toolbarKebabDropdownItems} + /> + + + {this.renderPagination()} + + + ); + + const PageNav = ( + + ); + + const userDropdownItems = [ + Link, + Action, + Disabled Link, + + Disabled Action + , + , + Separated Link, + Separated Action + ]; + + const PageToolbar = ( + + + + + + + + + + + + } + isOpen={isUpperToolbarKebabDropdownOpen} + dropdownItems={toolbarKebabDropdownItems} + /> + + + Kyle Baker} + dropdownItems={userDropdownItems} + /> + + + + ); + + const Header = ( + } + toolbar={PageToolbar} + avatar={} + showNavToggle + /> + ); + const Sidebar = ; + const pageId = 'main-content-card-view-default-nav'; + const PageSkipToContent = Skip to Content; + + const filtered = + filters.products.length > 0 + ? res.filter(card => { + return filters.products.length === 0 || filters.products.includes(card.name); + }) + : res; + + const icons = { + pfIcon, + activeMQIcon, + sparkIcon, + avroIcon, + azureIcon, + saxonIcon, + dropBoxIcon, + infinispanIcon, + restIcon, + swaggerIcon + }; + + return ( + + + + + Projects + This is a demo that showcases Patternfly Cards. + + + {toolbarItems} + + + + + {filtered.map((product, key) => ( + + + + + + this.onCardKebabDropdownSelect(key, e)} + toggle={ + + this.onCardKebabDropdownToggle(key, isCardKebabDropdownOpen) + } + /> + } + isOpen={this.state[key]} + dropdownItems={[ + + + Delete + + ]} + /> + + + + {product.name} + {product.description} + + + ))} + + + + + ); + } +} +``` diff --git a/packages/react-core/src/demos/CardView/examples/FuseConnector_Icons_AzureServices.png b/packages/react-core/src/demos/CardView/examples/FuseConnector_Icons_AzureServices.png new file mode 100644 index 00000000000..2b901285bf3 Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/FuseConnector_Icons_AzureServices.png differ diff --git a/packages/react-core/src/demos/CardView/examples/FuseConnector_Icons_REST.png b/packages/react-core/src/demos/CardView/examples/FuseConnector_Icons_REST.png new file mode 100644 index 00000000000..c37c95b5f5b Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/FuseConnector_Icons_REST.png differ diff --git a/packages/react-core/src/demos/CardView/examples/activemq-core_200x150.png b/packages/react-core/src/demos/CardView/examples/activemq-core_200x150.png new file mode 100644 index 00000000000..b022627b75e Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/activemq-core_200x150.png differ diff --git a/packages/react-core/src/demos/CardView/examples/camel-avro_200x150.png b/packages/react-core/src/demos/CardView/examples/camel-avro_200x150.png new file mode 100644 index 00000000000..4114648d355 Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/camel-avro_200x150.png differ diff --git a/packages/react-core/src/demos/CardView/examples/camel-dropbox_200x150.png b/packages/react-core/src/demos/CardView/examples/camel-dropbox_200x150.png new file mode 100644 index 00000000000..4c6237510bb Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/camel-dropbox_200x150.png differ diff --git a/packages/react-core/src/demos/CardView/examples/camel-infinispan_200x150.png b/packages/react-core/src/demos/CardView/examples/camel-infinispan_200x150.png new file mode 100644 index 00000000000..ad48236b44f Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/camel-infinispan_200x150.png differ diff --git a/packages/react-core/src/demos/CardView/examples/camel-saxon_200x150.png b/packages/react-core/src/demos/CardView/examples/camel-saxon_200x150.png new file mode 100644 index 00000000000..6b3110f7652 Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/camel-saxon_200x150.png differ diff --git a/packages/react-core/src/demos/CardView/examples/camel-spark_200x150.png b/packages/react-core/src/demos/CardView/examples/camel-spark_200x150.png new file mode 100644 index 00000000000..44ba194573a Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/camel-spark_200x150.png differ diff --git a/packages/react-core/src/demos/CardView/examples/camel-swagger-java_200x150.png b/packages/react-core/src/demos/CardView/examples/camel-swagger-java_200x150.png new file mode 100644 index 00000000000..2134e75e535 Binary files /dev/null and b/packages/react-core/src/demos/CardView/examples/camel-swagger-java_200x150.png differ diff --git a/packages/react-core/src/demos/CardView/examples/pf-logo-small.svg b/packages/react-core/src/demos/CardView/examples/pf-logo-small.svg new file mode 100644 index 00000000000..44c092431cb --- /dev/null +++ b/packages/react-core/src/demos/CardView/examples/pf-logo-small.svg @@ -0,0 +1,23 @@ + + + + Group 12 + Created with Sketch. + + + + + + + + + + + + + + + + + + \ No newline at end of file