UNPKG

c1-cms

Version:

Contains React components distributed with C1 CMS.

214 lines (205 loc) 6.08 kB
import React, { PropTypes } from 'react'; import ImmutablePropTypes from 'react-immutable-proptypes'; import Immutable from 'immutable'; import styled from 'styled-components'; import colors from 'console/components/colors.js'; import { setDialogState } from 'console/state/reducers/dialog.js'; import Icon from 'console/components/presentation/Icon.js'; // two-dimensional structure: Categories containing components. // Category has headline, open state, contains list of components // Component has preview image url, label, description const itemOpenCloseTime = '200ms'; const PaletteList = styled.div` margin-right: -10px; `; export const ItemGroup = styled.div` overflow: hidden; `; export const ItemGroupTop = styled.div` position: relative; display: inline-block; width: max-content; cursor: default; `; export const ItemGroupTitle = styled.h2` color: ${colors.dialogHeaderColor}; margin-top: 0; font-family: 'Roboto Condensed', sans-serif; font-style: italic; font-size: 14px; font-weight: normal; text-transform: uppercase; `; export const ItemGroupSwitch = styled(Icon)` position: absolute; right: -15px; top: 3px; height: 10px; width: 10px; `; export const ItemGroupCount = styled.div` position: absolute; right: -20px; transform: translateX(100%); top: 0; `; export const Item = styled.div` float: left; width: 420px; height: ${props => props.closed ? 0 : 140}px; margin-right: 15px; margin-bottom: ${props => props.closed ? 0 : 15}px; position: relative; background-color: ${ props => props.active ? colors.darkBackground : 'white' }; border-radius: 5px; border-width: ${props => props.closed ? 0 : 1}px; border-color: ${colors.borderColor}; border-style: ${ props => props.active ? 'solid' : 'dashed' }; opacity: ${props => props.closed ? 0 : 1}; transition: opacity ${itemOpenCloseTime}, height ${itemOpenCloseTime}, border-width ${itemOpenCloseTime}, background-color ${itemOpenCloseTime}, margin-bottom ${itemOpenCloseTime}; `; export const PreviewImage = styled.div` width: 100px; height: 100px; position: absolute; left: 20px; top: 15px; padding: 5px; border-radius: 5px; border: 1px solid ${colors.borderColor}; background-color: white; background-image: url('${ props => props.image }'); background-position: center center; background-repeat: no-repeat; background-size: cover; `; export const PreviewIcon = styled(Icon)` width: 100px; height: 100px; position: absolute; left: 20px; top: 15px; padding: 5px; border-radius: 5px; border: 1px solid ${colors.borderColor}; background-color: white; `; export const InfoBox = styled.div` position: absolute; left: 150px; top: 15px; width: 260px; height: 112px; overflow-y: auto; `; export const Label = styled.h3` font-weight: normal; color: ${colors.fieldLabelColor}; margin: 0 0 10px; `; export const Description = styled.p` margin: 10px 0; `; export const NoComponentsLabel = styled.div` color: ${colors.fieldLabelColor}; margin: 150px auto; text-align: center; font-size: 24px; `; export const NoComponentsIcon = styled(Icon)` height: 60px; width: 60px; `; NoComponentsIcon.defaultProps = { id: 'close'}; function resolveMediaURI(uri) { return uri; } const Palette = props => { return <PaletteList> {props.itemGroups.size === 0 ? <NoComponentsLabel> <NoComponentsIcon/><br/> {props.paneDef.get('noItemsText')} </NoComponentsLabel> : null} {props.itemGroups.map(itemGroup => <ItemGroup key={itemGroup.get('name')}> <div> <ItemGroupTop onClick={() => { let closed = props.dialogData.get('closed') || Immutable.Map(); closed = closed.set(itemGroup.get('name'), !closed.get(itemGroup.get('name'))); props.dispatch( setDialogState( props.dialogName, props.dialogData .set('closed', closed) ) ); }}> <ItemGroupSwitch id={props.dialogData.getIn(['closed', itemGroup.get('name')]) ? 'chevron-right' : 'chevron-down' } /> <ItemGroupCount>({itemGroup.get('entries').size})</ItemGroupCount> <ItemGroupTitle>{itemGroup.get('title')}</ItemGroupTitle> </ItemGroupTop> </div> {itemGroup.get('entries').map(item => { let itemName = item.get('id'); const selectItem = () => props.dispatch( setDialogState( props.dialogName, props.dialogData .set('selectedItem', itemName) .set('selectedComponentDefinition', item.get('componentDefinition')) ) ); return <Item closed={props.dialogData.getIn(['closed', itemGroup.get('name')])} key={itemName} onClick={selectItem} onDoubleClick={() => { selectItem(); (props.nextAction && props.nextAction()); }} active={itemName === props.dialogData.get('selectedItem')}> { item.getIn(['componentImage', 'customImageUri']) ? <PreviewImage image={resolveMediaURI(item.getIn(['componentImage', 'customImageUri']))}/> : <PreviewIcon id={item.getIn(['componentImage', 'iconName']) || 'base-function-function'}/> } <InfoBox> <Label>{item.get('title')}</Label> <Description>{item.get('description')}</Description> </InfoBox> </Item>; }).toArray()} </ItemGroup> ).toArray()} </PaletteList>; }; Palette.propTypes = { dialogName: PropTypes.string.isRequired, dialogData: ImmutablePropTypes.mapContains({ selectedItem: PropTypes.string }), paneDef: ImmutablePropTypes.mapContains({ name: PropTypes.string.isRequired, headline: PropTypes.string }).isRequired, itemGroups: ImmutablePropTypes.listOf(ImmutablePropTypes.mapContains({ entries: ImmutablePropTypes.listOf(ImmutablePropTypes.map).isRequired })).isRequired, dispatch: PropTypes.func.isRequired, nextAction: PropTypes.func }; export default Palette;