diff --git a/packages/strapi-admin/admin/src/app.js b/packages/strapi-admin/admin/src/app.js index 9b16117a85..f4184a17fd 100644 --- a/packages/strapi-admin/admin/src/app.js +++ b/packages/strapi-admin/admin/src/app.js @@ -12,6 +12,8 @@ import 'sanitize.css/sanitize.css'; import 'react-datetime/css/react-datetime.css'; import 'bootstrap/dist/css/bootstrap.css'; import 'font-awesome/css/font-awesome.min.css'; +import '@fortawesome/fontawesome-free/css/all.css'; +import '@fortawesome/fontawesome-free/js/all.min.js'; import React from 'react'; import ReactDOM from 'react-dom'; diff --git a/packages/strapi-admin/package.json b/packages/strapi-admin/package.json index 7653e5acf9..2614236a86 100644 --- a/packages/strapi-admin/package.json +++ b/packages/strapi-admin/package.json @@ -27,6 +27,9 @@ "@buffetjs/icons": "^1.0.6", "@buffetjs/styles": "^1.0.5", "@buffetjs/utils": "^1.0.5", + "@fortawesome/fontawesome-free": "^5.11.2", + "@fortawesome/fontawesome-svg-core": "^1.2.25", + "@fortawesome/free-solid-svg-icons": "^5.11.2", "autoprefixer": "^9.5.1", "babel-loader": "^8.0.5", "bcryptjs": "^2.4.3", @@ -67,6 +70,7 @@ "react-router": "^5.0.0", "react-router-dom": "^5.0.0", "react-transition-group": "^2.9.0", + "react-virtualized": "^9.21.2", "reactstrap": "^5.0.0", "redux": "^4.0.1", "redux-immutable": "^4.0.0", diff --git a/packages/strapi-admin/webpack.alias.js b/packages/strapi-admin/webpack.alias.js index 00fff309fe..62a298417e 100644 --- a/packages/strapi-admin/webpack.alias.js +++ b/packages/strapi-admin/webpack.alias.js @@ -7,6 +7,8 @@ const alias = [ '@buffetjs/icons', '@buffetjs/styles', '@buffetjs/utils', + '@fortawesome/fontawesome-svg-core', + '@fortawesome/free-solid-svg-icons', 'classnames', 'history', 'hoist-non-react-statics', @@ -24,6 +26,7 @@ const alias = [ 'react-router', 'react-router-dom', 'react-transition-group', + 'react-virtualized', 'reactstrap', 'redux', 'redux-immutable', diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/CellRenderer.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/CellRenderer.js new file mode 100644 index 0000000000..32ac300176 --- /dev/null +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/CellRenderer.js @@ -0,0 +1,19 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import icons from './utils/icons'; + +const CellRenderer = ({ index, key, style }) => { + return ( +
+ +
+ ); +}; + +CellRenderer.propTypes = { + key: PropTypes.string.isRequired, + index: PropTypes.number.isRequired, + style: PropTypes.object.isRequired, +}; + +export default CellRenderer; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/Wrapper.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/Wrapper.js new file mode 100644 index 0000000000..abb5ab0a55 --- /dev/null +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/Wrapper.js @@ -0,0 +1,36 @@ +import styled from 'styled-components'; + +const Wrapper = styled.div` + height: 150px; + margin-top: -1px; + + .collection { + background-color: #fff; + } + + .cell { + width: 100%; + height: 100%; + display: flex; + justify-content: center; + align-items: center; + border-radius: 0.25rem; + // color: #fff; + color: black; + } + + .noCells { + position: absolute; + top: 0; + bottom: 0; + left: 0; + right: 0; + display: flex; + align-items: center; + justify-content: center; + font-size: 1em; + color: #bdbdbd; + } +`; + +export default Wrapper; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/index.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/index.js new file mode 100644 index 0000000000..502d3eaf26 --- /dev/null +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/index.js @@ -0,0 +1,58 @@ +import React from 'react'; +import { Label, ErrorMessage } from '@buffetjs/styles'; +import { AutoSizer, Collection } from 'react-virtualized'; +import PropTypes from 'prop-types'; +import CellRenderer from './CellRenderer'; +import Wrapper from './Wrapper'; +const GUTTER_SIZE = 0; + +import icons from './utils/icons'; + +const ComponentIconPicker = ({ error, label, name }) => { + const cellCount = icons.length; + + const cellSizeAndPositionGetter = ({ index }) => { + const columnCount = 16; + const columnPosition = index % (columnCount || 1); + const height = 48; + const width = 48; + const x = columnPosition * (GUTTER_SIZE + width); + const y = parseInt(index / 16, 10) * 48; + + return { + height, + width, + x, + y, + }; + }; + + return ( + + + + {({ width }) => { + return ( + + ); + }} + + {error && {error}} + + ); +}; + +ComponentIconPicker.propTypes = { + error: PropTypes.string, + label: PropTypes.string.isRequired, + name: PropTypes.string.isRequired, +}; + +export default ComponentIconPicker; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/utils/icons.js b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/utils/icons.js new file mode 100644 index 0000000000..f4ac2a45f7 --- /dev/null +++ b/packages/strapi-plugin-content-type-builder/admin/src/components/ComponentIconPicker/utils/icons.js @@ -0,0 +1,8 @@ +import { library } from '@fortawesome/fontawesome-svg-core'; +import { fas } from '@fortawesome/free-solid-svg-icons'; + +library.add(fas); + +const icons = Object.keys(library.definitions.fas); + +export default icons; diff --git a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js index 7ede721f6c..8166eb65d9 100644 --- a/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js +++ b/packages/strapi-plugin-content-type-builder/admin/src/containers/FormModal/index.js @@ -20,6 +20,7 @@ import useQuery from '../../hooks/useQuery'; import useDataManager from '../../hooks/useDataManager'; import AttributeOption from '../../components/AttributeOption'; import BooleanBox from '../../components/BooleanBox'; +import ComponentIconPicker from '../../components/ComponentIconPicker'; import CustomCheckbox from '../../components/CustomCheckbox'; import CreatableSelect from '../../components/CreatableSelect'; import ModalHeader from '../../components/ModalHeader'; @@ -544,6 +545,7 @@ const FormModal = () => {