diff --git a/packages/components/List/index.js b/packages/components/List/index.js
new file mode 100644
index 0000000..f1c9083
--- /dev/null
+++ b/packages/components/List/index.js
@@ -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 (
+
+ );}
+
+ return null;
+ }).filter(item => {
+ return item !== null;
+ });
+
+ return (
+
+ {items !== null && items.length !== 0 ? : null}
+ {listItems}
+
+ );
+};
+
+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;
\ No newline at end of file
diff --git a/packages/components/List/stories/index.stories.js b/packages/components/List/stories/index.stories.js
new file mode 100644
index 0000000..28c2670
--- /dev/null
+++ b/packages/components/List/stories/index.stories.js
@@ -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', () =>
+
+ );
+
+storiesOf('List/Search Bar', module)
+ .addDecorator(StoryRouter())
+ .add('Default', () => {
+ return (
+
+ );
+ });
\ No newline at end of file
diff --git a/packages/components/SearchBar/index.js b/packages/components/SearchBar/index.js
new file mode 100644
index 0000000..858694a
--- /dev/null
+++ b/packages/components/SearchBar/index.js
@@ -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 (
+
+ setToggleShowInput(!toggleSearchInput) }
+ >
+
+
+
+
+
+
+ );
+};
+
+SearchBar.propTypes = {
+ handleSearch: PropTypes.func.isRequired,
+};
+
+SearchBar.defaultProps = {
+ handleSearch: () => {
+ console.log('Searching...');
+ },
+};
+
+export default SearchBar;
\ No newline at end of file
diff --git a/packages/components/SimpleCard/index.js b/packages/components/SimpleCard/index.js
index 23b3366..0607e07 100644
--- a/packages/components/SimpleCard/index.js
+++ b/packages/components/SimpleCard/index.js
@@ -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 (
-
+
{this.props.title}
@@ -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,
@@ -103,9 +100,6 @@ SimpleCard.defaultProps = {
handleDelete: () => {
console.log('Delete button clicked');
},
- showLinkPath: () => {
- console.log('Card clicked');
- }
};
export default SimpleCard;
diff --git a/packages/components/SimpleCard/stories/index.stories.js b/packages/components/SimpleCard/stories/index.stories.js
index 0d821ee..3e11c03 100644
--- a/packages/components/SimpleCard/stories/index.stories.js
+++ b/packages/components/SimpleCard/stories/index.stories.js
@@ -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())
@@ -24,8 +25,9 @@ storiesOf('Simple Card', module)
id={ item.id }
title={ item.title }
description={ item.description }
+ url={ item.url }
{ ...cardActions }
/>
);
- });
\ No newline at end of file
+ });