Skip to content

Commit

Permalink
Merge pull request #14 from bbc/adds-list-component
Browse files Browse the repository at this point in the history
Adds list component
  • Loading branch information
allishultes authored Aug 30, 2019
2 parents 8b1c3df + 24af036 commit 5a342f4
Show file tree
Hide file tree
Showing 5 changed files with 219 additions and 17 deletions.
105 changes: 105 additions & 0 deletions packages/components/List/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,105 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import SimpleCard from '../SimpleCard';
import SearchBar from '../SearchBar';

const List = ({ projectItems, handleEdit, handleDelete }) => {

const [ items, setItems ] = useState(projectItems);

const includesText = (text, subsetText) => {
return text.toLowerCase().includes(subsetText.toLowerCase().trim());
};

const handleDeleteItem = async (itemId) => {
const updatedList = items.filter((item) => {
return item.id !== itemId;
});
handleDelete(itemId);
setItems(updatedList);
};

// This is the original handleDelete, which took place at the page level:
// https://github.com/bbc/digital-paper-edit-client/blob/ba1924e89592fc8cd75fcb1e450ea15bc2599d95/src/Components/Projects/index.js
//
// const result = await ApiWrapper.deleteProject(itemId);
// if (result.ok) {
// const newItemsList = this.state.items.filter((p) => {
// return p.id !== itemId;
// });
// this.setState({ items: newItemsList });
// } else {
// // TODO: some error handling, error message saying something went wrong
// }

const handleDisplay = (item, searchText) => {
if (
includesText(item.title, searchText) ||
includesText(item.description, searchText)
) {
item.display = true;
} else {
item.display = false;
}

return item;
};

const handleSearchItem = searchText => {
const results = items.filter(item => handleDisplay(item, searchText));
setItems(results);
};

const listItems = items.map((item) => {
if (item.display) {
return (
<SimpleCard
key={ item.id }
id={ item.id }
title={ item.title }
description={ item.description }
url={ item.url }
handleEdit={ handleEdit }
handleDelete={ handleDeleteItem }
/>
);}

return null;
}).filter(item => {
return item !== null;
});

return (
<section style={ { height: '75vh', overflow: 'scroll' } }>
{items !== null && items.length !== 0 ? <SearchBar handleSearch={ handleSearchItem }/> : null}
{listItems}
</section>
);
};

List.propTypes = {
projectItems: PropTypes.array.isRequired,
handleEdit: PropTypes.func.isRequired,
handleDelete: PropTypes.func.isRequired,
};

List.defaultProps = {
projectItems: {
itemOne: {
id: '1234',
key: 'abc123',
title: 'Sample Simple Card Title One',
description: 'This is a sample card description. This is fun!',
display: true,
url: '/projects/1/transcripts/5678'
}
},
handleEdit: () => {
console.log('Edit button clicked');
},
handleDelete: () => {
console.log('Delete button clicked');
},
};

export default List;
49 changes: 49 additions & 0 deletions packages/components/List/stories/index.stories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
import React from 'react';

import { storiesOf } from '@storybook/react';
import { actions } from '@storybook/addon-actions';
import StoryRouter from 'storybook-react-router';
import List from '../index.js';
import SearchBar from '../../SearchBar';

import { item, cardActions } from '../../SimpleCard/stories/index.stories.js';

export const searchActions = actions({ handleSearch: 'Handle search' });

export const items = [ {
...item,
id: '1234',
key: 'abc123',
title: 'Sample Simple Card Title One',
description: 'This is a sample card description. This is fun!',
display: true,
}, { ...item,
id: '5678',
key: 'def456',
title: 'Sample Simple Card Title Two',
description: 'This is a sample card description. This is fun!',
display: true,
url: '/projects/1/transcripts/5678'
} ];

storiesOf('List', module)
.addDecorator(StoryRouter())
.add('With Simple Cards', () =>
<List
projectItems={ items }
{ ...cardActions }
{ ...searchActions }
/>
);

storiesOf('List/Search Bar', module)
.addDecorator(StoryRouter())
.add('Default', () => {
return (
<section style={ { height: '75vh', overflow: 'scroll' } }>
<SearchBar
{ ...searchActions }
/>
</section>
);
});
52 changes: 52 additions & 0 deletions packages/components/SearchBar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
import React, { useState } from 'react';
import PropTypes from 'prop-types';
import InputGroup from 'react-bootstrap/InputGroup';
import FormControl from 'react-bootstrap/FormControl';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import {
faSearch,
} from '@fortawesome/free-solid-svg-icons';

const SearchBar = ({ handleSearch }) => {

const [ toggleSearchInput, setToggleShowInput ] = useState(false);

const [ searchValue, setSearchValue ] = useState('');

const handleSearchInputChanges = (e) => {
handleSearch(e.target.value);
setSearchValue(e.target.value);
};

return (
<InputGroup className="mb-3">
<InputGroup.Prepend
onClick={ () => setToggleShowInput(!toggleSearchInput) }
>
<InputGroup.Text id="basic-addon2">
<FontAwesomeIcon icon={ faSearch } />
</InputGroup.Text>
</InputGroup.Prepend>
<FormControl
style={ { display: toggleSearchInput ? '' : 'none' } }
value={ searchValue }
onChange={ handleSearchInputChanges }
placeholder="Search"
aria-label="search"
aria-describedby="search"
/>
</InputGroup>
);
};

SearchBar.propTypes = {
handleSearch: PropTypes.func.isRequired,
};

SearchBar.defaultProps = {
handleSearch: () => {
console.log('Searching...');
},
};

export default SearchBar;
24 changes: 9 additions & 15 deletions packages/components/SimpleCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -14,30 +14,26 @@ import 'bootstrap-css-only/css/bootstrap.css';

class SimpleCard extends Component {
handleDelete = () => {
const confirmDeleteText = "Click OK if you wish to delete or cancel if you don't";
const cancelDeleteText = "All is good, it was not deleted";
const confirmationPrompt = confirm(confirmDeleteText);
if (confirmationPrompt) {
this.props.handleDelete ? this.props.handleDelete(this.props.id) : alert(cancelDeleteText);
}
const confirmDeleteText = "Click OK if you wish to delete or cancel if you don't";
const cancelDeleteText = 'All is good, it was not deleted';
const confirmationPrompt = confirm(confirmDeleteText);

if (confirmationPrompt) {
this.props.handleDelete ? this.props.handleDelete(this.props.id) : alert(cancelDeleteText);
}
};

handleEdit = () => {
this.props.handleEdit(this.props.id);
}

showLinkPath = () => {
return this.props.showLinkPath(this.props.id) || '';
}

render() {

return (
<Card style={ { width: '100%', marginBottom: '1em' } }>
<Card.Body>
<Row>
<LinkContainer to={ this.showLinkPath() } style={ { cursor: 'pointer' } }>
<LinkContainer to={ `${ this.props.url }` } style={ { cursor: 'pointer' } }>
<Col xs={ 8 } sm={ 10 }>
<Card.Title>
{this.props.title}
Expand Down Expand Up @@ -86,6 +82,7 @@ SimpleCard.propTypes = {
key: PropTypes.string.isRequired,
id: PropTypes.string.isRequired,
title: PropTypes.string.isRequired,
url: PropTypes.string.isRequired,
description: PropTypes.string,
handleEdit: PropTypes.func,
handleDelete: PropTypes.func,
Expand All @@ -103,9 +100,6 @@ SimpleCard.defaultProps = {
handleDelete: () => {
console.log('Delete button clicked');
},
showLinkPath: () => {
console.log('Card clicked');
}
};

export default SimpleCard;
6 changes: 4 additions & 2 deletions packages/components/SimpleCard/stories/index.stories.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,9 +10,10 @@ export const item = {
key: 'abc123',
title: 'Sample Simple Card Title',
description: 'This is a sample card description. This is fun!',
url: '/projects/1/transcripts/1234'
};

const cardActions = actions({ handleEdit: 'Edit button clicked', handleDelete: 'Delete button clicked', showLinkPath: 'Card clicked' });
export const cardActions = actions({ handleEdit: 'Edit button clicked', handleDelete: 'Delete button clicked' });

storiesOf('Simple Card', module)
.addDecorator(StoryRouter())
Expand All @@ -24,8 +25,9 @@ storiesOf('Simple Card', module)
id={ item.id }
title={ item.title }
description={ item.description }
url={ item.url }
{ ...cardActions }
/>
</section>
);
});
});

0 comments on commit 5a342f4

Please sign in to comment.