Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
cerebrl committed Aug 13, 2019
0 parents commit c242fdb
Show file tree
Hide file tree
Showing 38 changed files with 15,730 additions and 0 deletions.
29 changes: 29 additions & 0 deletions .editorconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# This file is for unifying the coding style for different editors and IDEs.
# More information at http://EditorConfig.org

[*]
indent_style = tab
indent_size = 4
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true
insert_final_newline = true

[.{babel,eslint,jslint,jshint,jscs}rc]
indent_style = tab
indent_size = 4

# Use 1 tab for public files (per uie.paypal.com)
[*.{es6,js,json,less,dust}]
indent_style = tab
indent_size = 4

# Use 4 spaces for indentation in Markdown files
[*.md]
trim_trailing_whitespace = false
indent_style = space
indent_size = 4

[package.json]
indent_style = space
indent_size = 2
32 changes: 32 additions & 0 deletions .eslintrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
module.exports = {
parser: '@typescript-eslint/parser', // Specifies the ESLint parser
extends: [
'plugin:@typescript-eslint/recommended', // Uses the recommended rules from the @typescript-eslint/eslint-plugin
'plugin:react/recommended', // basic rules for React
'plugin:prettier/recommended', // Enables eslint-plugin-prettier and displays prettier errors as ESLint errors. Make sure this is always the last configuration in the extends array.
'prettier/@typescript-eslint', // Uses eslint-config-prettier to disable ESLint rules from @typescript-eslint/eslint-plugin that would conflict with prettier
],
parserOptions: {
'ecmaVersion': 2018, // Allows for the parsing of modern ECMAScript features
'sourceType': 'module',
'ecmaFeatures': {
'jsx': true, // Allows for the parsing of JSX
}
},
plugins: [
'@typescript-eslint',
'react'
],
rules: {
// Place to specify ESLint rules. Can be used to overwrite rules specified from the extended configs
// e.g. "@typescript-eslint/explicit-function-return-type": "off"
'@typescript-eslint/indent': ['error', 'tab' ],
'@typescript-eslint/no-explicit-any': 0,
'useTabs': 0
},
settings: {
'react': {
'version': 'detect' // Tells eslint-plugin-react to automatically detect the version of React to use
}
}
};
21 changes: 21 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
.idea
.vscode

*.iml
out
gen
.DS_Store
node_modules/
users/
system
npm-debug.log

*.js
*.js.map
!public/*.js
!react-test-setup.js
!webpack.config.js
!.editorconfig
!.eslintrc.js
!.prettierrc.js
!jest.config.js
9 changes: 9 additions & 0 deletions .prettierrc.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
module.exports = {
semi: true,
trailingComma: 'none',
singleQuote: true,
printWidth: 120,
useTabs: true,
jsxSingleQuote: true,
arrowParens: 'always'
};
100 changes: 100 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
# "Offline-First" TodoMVC Example

## Up and Running

1. Install the dependencies found in the `package.json`
2. Compile the TypeScript to JavaScript
3. Run the server

```
npm install
npm run build
```

4. Open `public/index.html` in your browser.

## What's an "offline-first" application?

Coming soon ...

Here's the full tech-stack that we've chosen to execute this idea:

- **TypeScript**: used for transpiling (JSX and ES6) and module bundling for universal module design
- **React**: the V in MVC
- **Express**: our lightweight, un-opinionated, server framework
- **Page.js**: our client side routing technology
- **PouchDB**: for data storage and future "offline" capabilities

#### A bit on the top 4:

> TypeScript is a language for application-scale JavaScript development. TypeScript is a typed superset of JavaScript that compiles to plain JavaScript. Any browser. Any host. Any OS. Open Source.
>
> _[TypeScript - typescriptlang.org](http://typescriptlang.org)_
> React is a JavaScript library for creating user interfaces. Its core principles are declarative code, efficiency, and flexibility. Simply specify what your component looks like and React will keep it up-to-date when the underlying data changes.
>
> _[React - facebook.github.io/react](http://facebook.github.io/react)_
## Learning TypeScript

The [TypeScript website](http://typescriptlang.org) is a great resource for getting started.

Here are some links you may find helpful:

- [Tutorial](http://www.typescriptlang.org/Tutorial)
- [Code Playground](http://www.typescriptlang.org/Playground)
- [Documentation](https://github.com/Microsoft/TypeScript/wiki)
- [Applications built with TypeScript](http://www.typescriptlang.org/Samples)
- [Blog](http://blogs.msdn.com/b/typescript)
- [Source Code](https://github.com/Microsoft/TypeScript)

Articles and guides from the community:

- [Thoughts on TypeScript](http://www.nczonline.net/blog/2012/10/04/thoughts-on-typescript)
- [ScreenCast - Why I Like TypeScript](http://www.leebrimelow.com/why-i-like-typescripts)

Get help from other TypeScript users:

- [TypeScript on StackOverflow](http://stackoverflow.com/questions/tagged/typescript)
- [Forums](https://github.com/Microsoft/TypeScript/issues)
- [TypeScript on Twitter](http://twitter.com/typescriptlang)

_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._

## Learning Express

Express has been around for a very long time, so documentation is ubiquitous. But, if you need a reference, the framework's main site is the place to go: http://expressjs.com/.

## Learning React

The [React getting started documentation](http://facebook.github.io/react/docs/getting-started.html) is a great way to get started.

Here are some links you may find helpful:

- [Documentation](http://facebook.github.io/react/docs/getting-started.html)
- [API Reference](http://facebook.github.io/react/docs/reference.html)
- [Blog](http://facebook.github.io/react/blog/)
- [React on GitHub](https://github.com/facebook/react)
- [Support](http://facebook.github.io/react/support.html)

Articles and guides from the community:

- [How is Facebook's React JavaScript library](http://www.quora.com/React-JS-Library/How-is-Facebooks-React-JavaScript-library)
- [React: Under the hood](http://www.quora.com/Pete-Hunt/Posts/React-Under-the-Hood)

Get help from other React users:

* [React on StackOverflow](http://stackoverflow.com/questions/tagged/reactjs)
* [Discussion Forum](https://discuss.reactjs.org/)

_If you have other helpful links to share, or find any of the links above no longer work, please [let us know](https://github.com/tastejs/todomvc/issues)._

## How it works

Coming soon ...

## TODO

- [ ] Get the app to rerender when the PouchDB is updated
- [x] Get the TodoMVC app to render todos stored within IndexedDB using PouchDB
- [x] Initialize the application from [this previous TodoMVC application](https://github.com/cerebralideas/todomvc-universal-react-pouchdb)
13 changes: 13 additions & 0 deletions client/actions/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { createAction } from 'redux-actions';

export const addTodo = createAction('ADD_TODO', (title): { title: string } => ({ title }));
export const deleteTodo = createAction('DELETE_TODO', (id): { id: number } => ({ id }));
export const editTodo = createAction('EDIT_TODO', (id, title): { id: number; title: string } => ({ id, title }));
export const completeTodo = createAction('COMPLETE_TODO', (id): { id: number } => ({ id }));
export const completeAll = createAction('COMPLETE_ALL', (): {} => ({}));
export const clearCompleted = createAction('CLEAR_COMPLETED', (): {} => ({}));
export const showAll = createAction('SHOW_ALL', (): { filter: string } => ({ filter: 'show_all' }));
export const showActive = createAction('SHOW_ACTIVE', (): { filter: string } => ({ filter: 'show_active' }));
export const showCompleted = createAction('SHOW_COMPLETED', (): { filter: string } => ({
filter: 'show_completed'
}));
101 changes: 101 additions & 0 deletions client/components/footer.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
import React from 'react';
import { AppContext } from '../store/state-mgmt';
import { completeAll, clearCompleted } from '../events/client-events';
import { SHOW_ALL, SHOW_COMPLETED, SHOW_ACTIVE } from '../constants/todo-filters';

import { State } from '../interfaces';

let FILTER_TITLES = {
[SHOW_ALL]: 'All',
[SHOW_ACTIVE]: 'Active',
[SHOW_COMPLETED]: 'Completed'
};

interface Props {
completed?: number;
count?: number;
filter?: string;
active?: number;
}

function Footer({ filter, count, completed, active }: Props) {

if (count) {
function RenderTodoCount() {
let itemWord = active === 1 ? 'item' : 'items';

return (
<span className="todo-count">
<strong>{ active || 'No' }</strong> { itemWord } left
</span>
);
}

function RenderFilterLink({ filterType }) {
let title = FILTER_TITLES[filterType];
let isSelected = filter === filterType ? 'selected' : '';

return (
<a className={ isSelected }
href={ filterType }
style={{ cursor: 'pointer' }}>
{ title }
</a>
);
}

function RenderClearButton() {
if (completed > 0) {
return (
<button className="clear-completed"
onClick={ () => clearCompleted() }>
Clear completed
</button>
);
} else {
return null;
}
}

return (
<footer className="footer">
<RenderTodoCount />
<ul className="filters">
{[ SHOW_ALL, SHOW_ACTIVE, SHOW_COMPLETED ].map((filterType) =>
<li key={filterType}>
<RenderFilterLink filterType={ filterType } />
</li>
)}
</ul>
<RenderClearButton />
</footer>
);
} else {
return null;
}
}

export default function () {
return (
<AppContext.Consumer>
{ ({ todos, filter }) => {
let count = todos.length,
completed = todos.reduce((count, todo) => (
todo.completed ? count + 1 : count
),
0
),
active = count - completed;

return (
<Footer
filter={ filter }
count={ count }
completed={ completed }
active={ active }
/>
);
}}
</AppContext.Consumer>
);
}
36 changes: 36 additions & 0 deletions client/components/header.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
import React from 'react';
import { AppContext } from '../store/state-mgmt';
import TodoTextInput from './todo-text-input';

import { State } from '../interfaces';

function Header({ filter }: { filter: string }) {
let newTodo = true,
fakeTodo = {
editing: false,
title: ''
};

return (
<header className="header">
<h1>todos</h1>
<TodoTextInput todo={ fakeTodo }
newTodo={ newTodo }
filter={filter}
placeholder="What needs to be done?" />
</header>
);
}


export default function () {
return (
<AppContext.Consumer>
{({ filter }) => {
return (
<Header filter={ filter } />
);
}}
</AppContext.Consumer>
)
}
Loading

0 comments on commit c242fdb

Please sign in to comment.