-
Notifications
You must be signed in to change notification settings - Fork 0
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
develop #1
Open
falconx
wants to merge
28
commits into
master
Choose a base branch
from
develop
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Open
develop #1
Changes from all commits
Commits
Show all changes
28 commits
Select commit
Hold shift + click to select a range
75bee68
feat: add basic components and types
falconx 16474a2
feat: add localstorage support for global state
falconx 89c4409
improve state management and allow for column titles to be modified
falconx 25baa87
feat: allow cards to be added
falconx 15e1859
feat: allow adding new columns
falconx 50faa2b
fix: clear add new card fields on save
falconx b3a7d86
feat: allow removing columns
falconx 3835b74
feat: minor style improvements
falconx fa61615
test: add tests for api
falconx 6635f54
fix: prevent empty section name
falconx 0bfd230
refactor: flatten state
falconx 0f8696d
fix: add missing main landmark
falconx 2f4b1a0
fix: modal closing when click is fired within the content area
falconx a3856bc
fix: modal remounting
falconx ece20fc
feat: support card description
falconx 28db557
feat: show clamped card description
falconx 22c89c8
feat: allow dragging cards between columns
falconx 566ed93
feat: improve styles
falconx 0d25f41
refactor: remove references to weight
falconx e01ab53
feat: add default board state to demonstrate example usage
falconx 8378531
feat: introduce Input component
falconx 34d1d4e
fix: document title
falconx 01fd865
test: add more test cases
falconx 2aecdf7
docs: update README.md
falconx b519e9d
fix: column should not be draggable
falconx 5cc903a
docs: update typo
falconx 602e4b5
fix: drag and drop behaviour
falconx 57b8822
docs: update README
falconx File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,46 +1,48 @@ | ||
# Getting Started with Create React App | ||
|
||
This project was bootstrapped with [Create React App](https://github.com/facebook/create-react-app). | ||
|
||
## Available Scripts | ||
|
||
In the project directory, you can run: | ||
|
||
### `npm start` | ||
|
||
Runs the app in the development mode.\ | ||
Open [http://localhost:3000](http://localhost:3000) to view it in the browser. | ||
|
||
The page will reload if you make edits.\ | ||
You will also see any lint errors in the console. | ||
|
||
### `npm test` | ||
|
||
Launches the test runner in the interactive watch mode.\ | ||
See the section about [running tests](https://facebook.github.io/create-react-app/docs/running-tests) for more information. | ||
# Quick start | ||
|
||
### `npm run build` | ||
```bash | ||
yarn # Install dependencies | ||
yarn start # Run the app in dev mode | ||
``` | ||
|
||
Builds the app for production to the `build` folder.\ | ||
It correctly bundles React in production mode and optimizes the build for the best performance. | ||
# Deployments | ||
|
||
The build is minified and the filenames include the hashes.\ | ||
Your app is ready to be deployed! | ||
Pushing to the `develop` branch will trigger a deploy to https://trello-nine.vercel.app | ||
|
||
See the section about [deployment](https://facebook.github.io/create-react-app/docs/deployment) for more information. | ||
# What else you would've added to the project if this was going to be released as a real app? | ||
|
||
### `npm run eject` | ||
## Features | ||
|
||
**Note: this is a one-way operation. Once you `eject`, you can’t go back!** | ||
* Add an image field for each card to allows users to specify an image to show in the edit modal and card preview | ||
* Add routing support for cards so that each edit modal view is mounted at `/:card-id` | ||
* Update document title with the card title to improve SEO | ||
* Form validation with error messages | ||
* Enhance reordering | ||
* Allow for cards to be reordered within a column | ||
* Allow for columns to be reordered | ||
* Add touch support | ||
* In a real app I would make use of a well-established library for managing the drag and drop behaviour | ||
* User accounts and authentication | ||
* Assign users to cards | ||
* Checklists | ||
* Search | ||
* Images | ||
* Deadline dates | ||
|
||
If you aren’t satisfied with the build tool and configuration choices, you can `eject` at any time. This command will remove the single build dependency from your project. | ||
## Accessibility improvements | ||
|
||
Instead, it will copy all the configuration files and the transitive dependencies (webpack, Babel, ESLint, etc) right into your project so you have full control over them. All of the commands except `eject` will still work, but they will point to the copied scripts so you can tweak them. At this point you’re on your own. | ||
* It's currently not possible to reorder cards using only a keyboard — To solve this we could have a dropdown field within the edit modal view which lists all the available column titles and, on selection, reassigns the card `columnId` | ||
* There are lots of a11y considerations for modals, the easiest way to meet these standards is by using [react-modal](https://github.com/reactjs/react-modal) | ||
* It is currently not possible to hide the add card and add list fields using only a keyboard | ||
* Hover/focus styles | ||
|
||
You don’t have to ever use `eject`. The curated feature set is suitable for small and middle deployments, and you shouldn’t feel obligated to use this feature. However we understand that this tool wouldn’t be useful if you couldn’t customize it when you are ready for it. | ||
## Issues | ||
|
||
## Learn More | ||
1. Prevent body scrolling on when modal is present — Mostly an issue on mobile | ||
1. `activeDragCardId` state will unnecessarily be stored in localStorage (See `AppContext.tsx`) | ||
|
||
You can learn more in the [Create React App documentation](https://facebook.github.io/create-react-app/docs/getting-started). | ||
Not a big deal now but could bloat our local storage when adding more features which require temporary global state. | ||
|
||
To learn React, check out the [React documentation](https://reactjs.org/). | ||
We could have a separate typedef for stored global state and have `activeDragCard` use `useState` instead of `useLocalStorage`. |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file was deleted.
Oops, something went wrong.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,44 @@ | ||
:root { | ||
--shadow: 0 1px 2px -1px #091e4240, 0 0 0 1px #091e4214; | ||
|
||
/* spacing scale */ | ||
--space-1: 0.375rem; | ||
--space-2: 0.5rem; | ||
--space-3: 0.625rem; | ||
--space-4: 0.75rem; | ||
--space-5: 0.875rem; | ||
--space-6: 1rem; | ||
--space-7: 1.125rem; | ||
|
||
/* type scale */ | ||
--text-small: 0.875rem; | ||
|
||
/* generic colors */ | ||
--c-white: #fff; | ||
--c-black: #222; | ||
--c-grey: #ebecf0; | ||
--c-light-grey: #5e6c84; | ||
--c-blue: #0079bf; | ||
--c-light-blue: #e2f4ff; | ||
--c-red: #d1576e; | ||
--c-light-red: #ffecec; | ||
|
||
/* component colors */ | ||
--c-overlay: #000000a3; | ||
--c-card: var(--c-white); | ||
--c-column: var(--c-grey); | ||
--c-column-drag-highlight: var(--c-light-blue); | ||
|
||
--c-button-primary: var(--c-blue); | ||
--c-button-primary-text: var(--c-white); | ||
--c-button-secondary: var(--c-light-blue); | ||
--c-button-secondary-text: var(--c-blue); | ||
--c-button-remove: var(--c-light-red); | ||
--c-button-remove-text: var(--c-red); | ||
--c-button-disabled: var(--c-grey); | ||
--c-button-disabled-text: var(--c-black); | ||
} | ||
|
||
body { | ||
font-family: Arial, Helvetica, sans-serif; | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,9 +1,28 @@ | ||
import React from 'react'; | ||
import { render, screen } from '@testing-library/react'; | ||
|
||
import App from './App'; | ||
|
||
test('renders learn react link', () => { | ||
render(<App />); | ||
const linkElement = screen.getByText(/learn react/i); | ||
expect(linkElement).toBeInTheDocument(); | ||
describe('App', () => { | ||
it('renders page header', async () => { | ||
render(<App />); | ||
|
||
const heading = await screen.findByRole('heading', { level: 1 }); | ||
expect(heading).toBeInTheDocument(); | ||
}); | ||
|
||
it('renders default column headers', async () => { | ||
render(<App />); | ||
|
||
let column; | ||
|
||
column = await screen.findByText('To Do'); | ||
expect(column).toBeInTheDocument(); | ||
|
||
column = await screen.findByText('In Progress'); | ||
expect(column).toBeInTheDocument(); | ||
|
||
column = await screen.findByText('Done'); | ||
expect(column).toBeInTheDocument(); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,26 +1,18 @@ | ||
import React from 'react'; | ||
import logo from './logo.svg'; | ||
import './App.css'; | ||
|
||
function App() { | ||
return ( | ||
<div className="App"> | ||
<header className="App-header"> | ||
<img src={logo} className="App-logo" alt="logo" /> | ||
<p> | ||
Edit <code>src/App.tsx</code> and save to reload. | ||
</p> | ||
<a | ||
className="App-link" | ||
href="https://reactjs.org" | ||
target="_blank" | ||
rel="noopener noreferrer" | ||
> | ||
Learn React | ||
</a> | ||
</header> | ||
</div> | ||
); | ||
} | ||
import { AppProvider } from './AppContext'; | ||
import Board from './components/Board'; | ||
|
||
import './App.module.css'; | ||
|
||
const App: React.FunctionComponent = () => ( | ||
<AppProvider> | ||
<main> | ||
<Board /> | ||
</main> | ||
|
||
<div id="modal-root" /> | ||
</AppProvider> | ||
); | ||
|
||
export default App; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import React from 'react'; | ||
|
||
describe('AppContext', () => { | ||
describe('stores app state in localStorage', () => { | ||
it.todo('addCard'); | ||
it.todo('removeCard'); | ||
it.todo('updateCard'); | ||
it.todo('addColumn'); | ||
it.todo('removeColumn'); | ||
it.todo('updateColumn'); | ||
}); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,111 @@ | ||
import React, { createContext } from 'react'; | ||
|
||
import { GlobalState } from './types/GlobalState'; | ||
import { Column, EditableColumnFields } from './types/Column'; | ||
import { Card, EditableCardFields } from './types/Card'; | ||
|
||
import * as api from './api'; | ||
import useLocalStorage from './hooks/useLocalStorage'; | ||
import { LOCAL_STORAGE_KEY } from './constants'; | ||
|
||
export interface GlobalAppContext { | ||
state: GlobalState; | ||
dragCard: (cardId: string) => void; | ||
addCard: (value: Card) => void; | ||
removeCard: (cardId: string) => void; | ||
updateCard: (cardId: string, value: EditableCardFields) => void; | ||
addColumn: (value: Column) => void; | ||
removeColumn: (columnId: string) => void; | ||
updateColumn: (columnId: string, value: EditableColumnFields) => void; | ||
} | ||
|
||
const defaultState: GlobalState = { | ||
columns: [ | ||
{ | ||
id: 'todo', | ||
title: 'To Do', | ||
}, | ||
{ | ||
id: 'in-progress', | ||
title: 'In Progress', | ||
}, | ||
{ | ||
id: 'done', | ||
title: 'Done', | ||
}, | ||
], | ||
cards: [ | ||
{ | ||
id: 'card-0', | ||
columnId: 'done', | ||
title: 'Make breakfast', | ||
description: `In order to make breakfast you'll need the following ingredients:\n\n* Eggs\n* Sausages\n* Beans\n* Hash browns\n* Toast`, | ||
}, | ||
{ | ||
id: 'card-1', | ||
columnId: 'todo', | ||
title: 'Check mail', | ||
}, | ||
{ | ||
id: 'card-2', | ||
columnId: 'todo', | ||
title: 'Get to work', | ||
}, | ||
], | ||
}; | ||
Comment on lines
+22
to
+55
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Given that it's easy to clear the board, I figured it was nice to show the user a default example usage. |
||
|
||
const noop = () => {}; | ||
|
||
const AppContext = createContext<GlobalAppContext>({ | ||
state: defaultState, | ||
dragCard: noop, | ||
addCard: noop, | ||
removeCard: noop, | ||
updateCard: noop, | ||
addColumn: noop, | ||
removeColumn: noop, | ||
updateColumn: noop, | ||
}); | ||
|
||
const AppConsumer = AppContext.Consumer; | ||
|
||
interface Props { | ||
children?: React.ReactNode; | ||
} | ||
|
||
const AppProvider: React.FunctionComponent<Props> = props => { | ||
const [state, setState] = useLocalStorage<GlobalState>(LOCAL_STORAGE_KEY, defaultState); | ||
|
||
// TODO: opted for conciseness here but type safety could be improved | ||
// by ensuring the context and api function signatures are matched | ||
const update = (fn: Function, ...args: any) => setState(fn(state, ...args)); | ||
|
||
const dragCard = (cardId: string) => { | ||
setState({ | ||
...state, | ||
activeDragCardId: cardId, | ||
}); | ||
}; | ||
|
||
return ( | ||
<AppContext.Provider | ||
value={{ | ||
state, | ||
addCard: update.bind(null, api.addCard), | ||
removeCard: update.bind(null, api.removeCard), | ||
updateCard: update.bind(null, api.updateCard), | ||
addColumn: update.bind(null, api.addColumn), | ||
removeColumn: update.bind(null, api.removeColumn), | ||
updateColumn: update.bind(null, api.updateColumn), | ||
dragCard, | ||
}} | ||
{...props} | ||
/> | ||
) | ||
}; | ||
|
||
export { | ||
AppContext, | ||
AppProvider, | ||
AppConsumer, | ||
}; |
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Initially I wrote this as:
however, apart from being more difficult to read, a test failure would only report that the
const column = await screen.findByText(text);
line failed, and not which of the scenarios was to blame.