Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Adds list component #14

Merged
merged 13 commits into from
Aug 30, 2019
Merged
76 changes: 76 additions & 0 deletions packages/components/List/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
import React, { useState } from 'react';
import SimpleCard from '../SimpleCard';
import SearchBar from '../SearchBar';

const List = ({ projectItems, handleSearch, 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;
});
allishultes marked this conversation as resolved.
Show resolved Hide resolved
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;
};

handleSearch = 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={handleSearch}/> : null}
{listItems}
</section>
</>
);
}

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>
);
});
42 changes: 42 additions & 0 deletions packages/components/SearchBar/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@

import React, { useState, useEffect } from 'react';
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>
);
}

export default SearchBar;
8 changes: 2 additions & 6 deletions packages/components/SimpleCard/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -26,18 +26,14 @@ class SimpleCard extends Component {
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
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>
);
});
});