From 2c65180aee661949b2003dc44829adfbe41dd79b Mon Sep 17 00:00:00 2001 From: tarikhuber Date: Sun, 18 Jun 2017 01:52:40 +0200 Subject: [PATCH] Implementation of query watchers --- README.md | 86 +++++------ demo/src/components/containers/About/About.js | 2 +- .../containers/Activity/Activity.js | 2 +- .../containers/Companies/Companies.js | 2 +- demo/src/components/containers/Tasks/Task.js | 2 +- demo/src/components/containers/Tasks/Tasks.js | 2 +- demo/src/components/containers/Users/Users.js | 2 +- demo/src/containers/About/About.js | 2 +- demo/src/containers/Activity/Activity.js | 2 +- demo/src/containers/Companies/Companie.js | 8 +- demo/src/containers/Companies/Companies.js | 9 +- demo/src/containers/Tasks/Task.js | 2 +- demo/src/containers/Tasks/Tasks.js | 2 +- demo/src/containers/Users/Users.js | 2 +- demo/src/index.js | 2 +- demo/src/store/reducers.js | 14 +- package-lock.json | 136 ++++++++++++------ package.json | 11 +- src/index.js | 13 ++ src/store/lists/actions.js | 55 +++++-- 20 files changed, 223 insertions(+), 133 deletions(-) diff --git a/README.md b/README.md index f681997..368984f 100644 --- a/README.md +++ b/README.md @@ -2,7 +2,7 @@ This project was bootstrapped with [nwb](https://github.com/insin/nwb) -Firekit was created to help working with Firebase in React Projects that use Redux as state storage. +Firekit was created to help working with Firebase in React Projects that use Redux as state storage. You can find a full functional **DEMO** project (React Most Wanted) with source code [here](https://www.react-most-wanted.com/). @@ -15,7 +15,7 @@ You can find a full functional **DEMO** project (React Most Wanted) with source - [Usage](#usage) - [Accessing firebaseApp](#accessing-firebaseapp) - [Connection](#connection) - - [Lists](#lists) + - [Lists and Queries](#lists-and-queires) - [Paths](#paths) - [FireForm](#fireform) - [TO DO](#to-do) @@ -26,7 +26,7 @@ You can find a full functional **DEMO** project (React Most Wanted) with source Firekit allows you to watch firebase data and sync it to your redux store with a minimum of code to write. It uses a `Provider` to server the `firebaseApp` to all Components that need it. Some features that are unque to this firebase toolkit are: -* **persistant watchers** - the watchers are persistant and are not linked to components. You deside when to watch a value in your firebase database and when to unwatch (turn off listeners) it. +* **persistant watchers** - the watchers are persistant and are not linked to components. You deside when to watch a value in your firebase database and when to unwatch (turn off listeners) it. * **your create firebaseApp** - you initialise the firebaseApp how you want and add it as prop to the firekit `FirebaseProvider` and all your components have access to the firebaseApp @@ -36,7 +36,7 @@ Some features that are unque to this firebase toolkit are: * **native firebase** - you can use firebases native sdk for the web. Firekit is just listening on changes. Every change on the data you can make as it is described in the official firebase documentation -* **realtime forms** - firekit has a special Warapper for `redux-forms` witch allows to sync them with the realtime database very simple and plus it is automaticaly synced on field changes in real time if they ocure while your are in the Form +* **realtime forms** - firekit has a special Warapper for `redux-forms` witch allows to sync them with the realtime database very simple and plus it is automaticaly synced on field changes in real time if they ocure while your are in the Form Features like populating values in the database are omited with purpose. The firebase `cloud functions` are the place where you should populate data that must be saved in multiple places. @@ -110,32 +110,27 @@ import dialogs from './dialogs/reducer'; import messaging from './messaging/reducer'; import locale from './locale/reducer'; import theme from './theme/reducer'; -import { - connectionReducer, - listsReducer, - pathsReducer, - initializationReducer -} from 'firekit'; //Import the reducers +import firekitReducers from 'firekit'; //Import the firekitReducers + + +console.log(firekitReducers); const reducers = combineReducers({ browser: responsiveStateReducer, responsiveDrawer, form: formReducer, auth, - initialization: initializationReducer, //Add the initialisation reducer - connection: connectionReducer, //Add the connection reducer - lists: listsReducer, //Add the lists reducer - paths: pathsReducer, //Add the paths reducer dialogs, messaging, locale, theme, + ...firekitReducers //Spread the firekit reducers }) export default reducers; ``` -In future versions the reducers will be combined in a single object that will be reducable. +To add all firekti reducers to your redux store just spread the firekitReducers object into your `comineReducers` object. **WARNING:** if you are using persistance take care that the reducer `initialization` is not persisted! He saves the watchers. If he would be persisted the watcher would not initialize again after a page reload. If you are using `redux-persist` just add him to the black list. @@ -143,13 +138,13 @@ In future versions the reducers will be combined in a single object that will be persistStore(store, {blacklist:['auth', 'form', 'connection', 'initialization'] }, ()=>{}); //Add initialization to persistance blacklist if you use persistance ``` -**INFO:** the reducers are not customasable so they have to use the names as they are here in the snipped. In future we could add customatisation for this so they could have any name you want. +**INFO:** the reducers are not customasable. In future we could add customatisation for this so they could have any name you want. ## Usage Let us now do something with our firekit :smile: -To use `firekit` in a component we need to tell the component to get all `firekit` props from the context. -We use for that a simple call `withFirebase`. It is very similar to the `react-router` call `withRouter`. The usage is exactly the same. +To use `firekit` in a component we need to tell the component to get all `firekit` props from the context. +We use for that a simple call `withFirebase`. It is very similar to the `react-router` call `withRouter`. The usage is exactly the same. Let us take a look on a simple component. @@ -247,7 +242,7 @@ class MyComponent extends Component { const { initConnection }= this.props; initConnection(); //Here we started watching the connection state } - + componentWillUnmount() { const { unsubscribeConnection, }= this.props; unsubscribeConnection(); // Here we unsunscribe the listening to the connection state @@ -276,9 +271,9 @@ export default connect( )(withFirebase(MyComponent)); ``` -### Lists +### Lists and Queries -We can easely observe lists in the realtime database using the `watchList` and `unwatchList` API calls. +We can easely observe lists in the realtime database using the `watchList` and `unwatchList` API calls. The same calls are used to observe Firebase queries. `watchList` and `unwatchList` can recieve as parameter a string to a database path or a Firebase reference to that path. If you have a simple reference to a path using just the string of the path is the right choice. But if you have a Firebase query reference you can send that reference with all its query calls as parameter. ```js import React, { Component } from 'react'; @@ -289,18 +284,25 @@ import _ from 'lodash'; class MyComponent extends Component { componentDidMount(){ - const { watchList }= this.props; - watchList('users'); //Here we started watching the list + const { watchList, firebaseApp }= this.props; + + watchList('users'); //Here we started watching the users list + + //Her we watch a simple firebase query + let tasksRef= firebaseApp.database().ref('tasks').limitToFirst(10); + watchList(tasksRef); + } - + componentWillUnmount() { const { unwatchList, }= this.props; unwatchList('users'); // We can unwatch the list on unmounting the Component + unwatchList('tasks'); // To unwatch a query qe can use just the ref path string } - + rednerList = () => { const {users} =this.props; - + if(users===undefined){ return
} @@ -336,9 +338,9 @@ export default connect( )(withFirebase(MyComponent)); ``` -Here we unwatched the list on `componentWillUnmount`. We could also leave this away and the list will change in realtime in the background and it will not load all data on revisiting the Component again. +Here we unwatched the list on `componentWillUnmount`. We could also leave this away and the list will change in realtime in the background and it will not load all data on revisiting the Component again. -If you are using persistand watcher you would have to unwatch them in some point of your application or on application exit. +If you are using persistand watcher you would have to unwatch them in some point of your application or on application exit. Because of that there are special calls that allow us to unwatch all persistand watcher in a single call. That could be calles in the root component of your application like this: ```js @@ -351,7 +353,7 @@ Because of that there are special calls that allow us to unwatch all persistand unwatchAllLists(); unwatchAllPaths(); } - + //... other code of your root Component ``` @@ -370,12 +372,12 @@ The paths watcher exactly like the lists watcher with `watchPath` and `unwatchPa const { watchPath }= this.props; watchPath('users_count'); //Here we started watching the path } - + componentWillUnmount() { const { unwatchPath, }= this.props; unwatchPath('users'); // We can unwatch the path on unmounting the Component } - + //... ``` @@ -395,15 +397,15 @@ And comes the cool thing. If you are in the Form working on fields and someone e //... - {history.push('/companies');}} - onDelete={(values)=>{history.push('/companies');}} - handleCreateValues={this.handleCreateValues} - uid={match.params.uid}> -
// Here is your simple form - + {history.push('/companies');}} + onDelete={(values)=>{history.push('/companies');}} + handleCreateValues={this.handleCreateValues} + uid={match.params.uid}> + // Here is your simple form + //... @@ -412,11 +414,11 @@ And comes the cool thing. If you are in the Form working on fields and someone e ## TO DO -- [ ] compine all reducer to one import +- [X] compine all reducer to one import - [ ] integrate selectors - [ ] integrate firebase messaging - [ ] integrate firebase auth watcher -- [ ] integrate firebase queries watcher +- [X] integrate firebase queries watcher ## License diff --git a/demo/src/components/containers/About/About.js b/demo/src/components/containers/About/About.js index 9a6f31e..4270e51 100644 --- a/demo/src/components/containers/About/About.js +++ b/demo/src/components/containers/About/About.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import {injectIntl, intlShape} from 'react-intl'; import { Activity } from '../../containers/Activity'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../src'; class About extends Component { diff --git a/demo/src/components/containers/Activity/Activity.js b/demo/src/components/containers/Activity/Activity.js index c86126c..218e0c7 100644 --- a/demo/src/components/containers/Activity/Activity.js +++ b/demo/src/components/containers/Activity/Activity.js @@ -15,7 +15,7 @@ import { darkWhite, } from 'material-ui/styles/colors'; import config from '../../config'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../src'; export class Activity extends Component { diff --git a/demo/src/components/containers/Companies/Companies.js b/demo/src/components/containers/Companies/Companies.js index 1f1854a..be49246 100644 --- a/demo/src/components/containers/Companies/Companies.js +++ b/demo/src/components/containers/Companies/Companies.js @@ -11,7 +11,7 @@ import FontIcon from 'material-ui/FontIcon'; import FloatingActionButton from 'material-ui/FloatingActionButton'; import {withRouter} from 'react-router-dom'; import Avatar from 'material-ui/Avatar'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../src'; class Vehicles extends Component { diff --git a/demo/src/components/containers/Tasks/Task.js b/demo/src/components/containers/Tasks/Task.js index 59fcd55..d0b5121 100644 --- a/demo/src/components/containers/Tasks/Task.js +++ b/demo/src/components/containers/Tasks/Task.js @@ -11,7 +11,7 @@ import firebase from 'firebase'; import FontIcon from 'material-ui/FontIcon'; import FlatButton from 'material-ui/FlatButton'; import Dialog from 'material-ui/Dialog'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../src'; const path='/public_tasks/'; diff --git a/demo/src/components/containers/Tasks/Tasks.js b/demo/src/components/containers/Tasks/Tasks.js index c57cce8..795c453 100644 --- a/demo/src/components/containers/Tasks/Tasks.js +++ b/demo/src/components/containers/Tasks/Tasks.js @@ -19,7 +19,7 @@ import {BottomNavigation} from 'material-ui/BottomNavigation'; import {withRouter} from 'react-router-dom'; import FlatButton from 'material-ui/FlatButton'; import Dialog from 'material-ui/Dialog'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../src'; class Tasks extends Component { diff --git a/demo/src/components/containers/Users/Users.js b/demo/src/components/containers/Users/Users.js index dfa33e1..4cbf1f3 100644 --- a/demo/src/components/containers/Users/Users.js +++ b/demo/src/components/containers/Users/Users.js @@ -11,7 +11,7 @@ import Avatar from 'material-ui/Avatar'; import FontIcon from 'material-ui/FontIcon'; import {GoogleIcon, FacebookIcon, GitHubIcon, TwitterIcon} from '../../components/Icons'; import IconButton from 'material-ui/IconButton'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../src'; class Users extends Component { diff --git a/demo/src/containers/About/About.js b/demo/src/containers/About/About.js index 9a6f31e..417fe1e 100644 --- a/demo/src/containers/About/About.js +++ b/demo/src/containers/About/About.js @@ -1,7 +1,7 @@ import React, { Component } from 'react'; import {injectIntl, intlShape} from 'react-intl'; import { Activity } from '../../containers/Activity'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../../../src'; class About extends Component { diff --git a/demo/src/containers/Activity/Activity.js b/demo/src/containers/Activity/Activity.js index c86126c..530ec7c 100644 --- a/demo/src/containers/Activity/Activity.js +++ b/demo/src/containers/Activity/Activity.js @@ -15,7 +15,7 @@ import { darkWhite, } from 'material-ui/styles/colors'; import config from '../../config'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../../../src'; export class Activity extends Component { diff --git a/demo/src/containers/Companies/Companie.js b/demo/src/containers/Companies/Companie.js index 2c678f8..0749491 100644 --- a/demo/src/containers/Companies/Companie.js +++ b/demo/src/containers/Companies/Companie.js @@ -10,7 +10,7 @@ import firebase from 'firebase'; import FontIcon from 'material-ui/FontIcon'; import FlatButton from 'material-ui/FlatButton'; import Dialog from 'material-ui/Dialog'; -import { firebaseDb } from '../../firebase'; +import { withFirebase } from '../../../../src'; const path='/companies/'; @@ -43,11 +43,11 @@ class Companie extends Component { handleDelete = () => { - const {history, match}=this.props; + const {history, match, firebaseApp}=this.props; const uid=match.params.uid; if(uid){ - firebaseDb.ref().child(`${path}${uid}`).remove().then(()=>{ + firebaseApp.database().ref().child(`${path}${uid}`).remove().then(()=>{ this.handleClose(); history.goBack(); }) @@ -122,4 +122,4 @@ const mapStateToProps = (state) => { export default connect( mapStateToProps, {setDialogIsOpen} -)(injectIntl(withRouter(Companie))); +)(injectIntl(withRouter(withFirebase(Companie)))); diff --git a/demo/src/containers/Companies/Companies.js b/demo/src/containers/Companies/Companies.js index 1f1854a..7637487 100644 --- a/demo/src/containers/Companies/Companies.js +++ b/demo/src/containers/Companies/Companies.js @@ -11,13 +11,16 @@ import FontIcon from 'material-ui/FontIcon'; import FloatingActionButton from 'material-ui/FloatingActionButton'; import {withRouter} from 'react-router-dom'; import Avatar from 'material-ui/Avatar'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../../../src'; class Vehicles extends Component { componentDidMount() { - const { watchList}=this.props; - watchList('companies'); + const { watchList, firebaseApp}=this.props; + + let ref=firebaseApp.database().ref('companies').limitToFirst(2); + + watchList(ref); } renderList(companies) { diff --git a/demo/src/containers/Tasks/Task.js b/demo/src/containers/Tasks/Task.js index 59fcd55..8c25302 100644 --- a/demo/src/containers/Tasks/Task.js +++ b/demo/src/containers/Tasks/Task.js @@ -11,7 +11,7 @@ import firebase from 'firebase'; import FontIcon from 'material-ui/FontIcon'; import FlatButton from 'material-ui/FlatButton'; import Dialog from 'material-ui/Dialog'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../../../src'; const path='/public_tasks/'; diff --git a/demo/src/containers/Tasks/Tasks.js b/demo/src/containers/Tasks/Tasks.js index c57cce8..1c093db 100644 --- a/demo/src/containers/Tasks/Tasks.js +++ b/demo/src/containers/Tasks/Tasks.js @@ -19,7 +19,7 @@ import {BottomNavigation} from 'material-ui/BottomNavigation'; import {withRouter} from 'react-router-dom'; import FlatButton from 'material-ui/FlatButton'; import Dialog from 'material-ui/Dialog'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../../../src'; class Tasks extends Component { diff --git a/demo/src/containers/Users/Users.js b/demo/src/containers/Users/Users.js index dfa33e1..f5892db 100644 --- a/demo/src/containers/Users/Users.js +++ b/demo/src/containers/Users/Users.js @@ -11,7 +11,7 @@ import Avatar from 'material-ui/Avatar'; import FontIcon from 'material-ui/FontIcon'; import {GoogleIcon, FacebookIcon, GitHubIcon, TwitterIcon} from '../../components/Icons'; import IconButton from 'material-ui/IconButton'; -import { withFirebase } from 'firekit'; +import { withFirebase } from '../../../../src'; class Users extends Component { diff --git a/demo/src/index.js b/demo/src/index.js index 5445430..9eeff49 100644 --- a/demo/src/index.js +++ b/demo/src/index.js @@ -1,7 +1,7 @@ import React, {Component} from 'react' import {render} from 'react-dom' import { Provider } from 'react-redux'; -import { FirebaseProvider } from 'firekit'; +import { FirebaseProvider } from '../../src'; import configureStore from './store'; import { Root } from './containers/Root'; import { addLocalizationData } from './locales'; diff --git a/demo/src/store/reducers.js b/demo/src/store/reducers.js index 375faf0..da8ec93 100644 --- a/demo/src/store/reducers.js +++ b/demo/src/store/reducers.js @@ -7,27 +7,21 @@ import dialogs from './dialogs/reducer'; import messaging from './messaging/reducer'; import locale from './locale/reducer'; import theme from './theme/reducer'; -import { - connectionReducer, - listsReducer, - pathsReducer, - initializationReducer -} from 'firekit'; +import firekitReducers from '../../../src'; +console.log(firekitReducers); + const reducers = combineReducers({ browser: responsiveStateReducer, responsiveDrawer, form: formReducer, auth, - initialization: initializationReducer, - connection: connectionReducer, - lists: listsReducer, - paths: pathsReducer, dialogs, messaging, locale, theme, + ...firekitReducers }) export default reducers; diff --git a/package-lock.json b/package-lock.json index b6fe4d4..97f7039 100644 --- a/package-lock.json +++ b/package-lock.json @@ -164,7 +164,8 @@ "asap": { "version": "2.0.5", "resolved": "https://registry.npmjs.org/asap/-/asap-2.0.5.tgz", - "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=" + "integrity": "sha1-UidltQw1EEkOUtfc/ghe+bqWlY8=", + "dev": true }, "asn1": { "version": "0.2.3", @@ -1490,7 +1491,8 @@ "core-js": { "version": "1.2.7", "resolved": "https://registry.npmjs.org/core-js/-/core-js-1.2.7.tgz", - "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=" + "integrity": "sha1-ZSKUwUZR2yj6k70tX/KYOk8IxjY=", + "dev": true }, "core-util-is": { "version": "1.0.2", @@ -1695,7 +1697,8 @@ "deep-equal": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/deep-equal/-/deep-equal-1.0.1.tgz", - "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=" + "integrity": "sha1-9dJgKStmDghO/0zbyfCK0yR0SLU=", + "dev": true }, "deep-extend": { "version": "0.4.2", @@ -1897,7 +1900,8 @@ "encoding": { "version": "0.1.12", "resolved": "https://registry.npmjs.org/encoding/-/encoding-0.1.12.tgz", - "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=" + "integrity": "sha1-U4tm8+5izRq1HsMjgp0flIDHS+s=", + "dev": true }, "end-of-stream": { "version": "1.4.0", @@ -2008,7 +2012,8 @@ "es6-error": { "version": "4.0.2", "resolved": "https://registry.npmjs.org/es6-error/-/es6-error-4.0.2.tgz", - "integrity": "sha1-7sXHJurO9Rt/a3PCDbbhsTsGnJg=" + "integrity": "sha1-7sXHJurO9Rt/a3PCDbbhsTsGnJg=", + "dev": true }, "es6-promise": { "version": "4.0.5", @@ -2250,7 +2255,8 @@ "fbjs": { "version": "0.8.12", "resolved": "https://registry.npmjs.org/fbjs/-/fbjs-0.8.12.tgz", - "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=" + "integrity": "sha1-ELXZL3bUVXX9Y6IX1OoCvqL47QQ=", + "dev": true }, "fd-slicer": { "version": "1.0.1", @@ -2318,90 +2324,112 @@ "version": "4.1.2", "resolved": "https://registry.npmjs.org/firebase/-/firebase-4.1.2.tgz", "integrity": "sha1-shOrIp62XjG9vR0mIFmxux7frB8=", + "dev": true, "dependencies": { "base64url": { "version": "https://registry.npmjs.org/base64url/-/base64url-2.0.0.tgz", - "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=" + "integrity": "sha1-6sFuA+oUOO/5Qj1puqNiYu0fcLs=", + "dev": true }, "buffer-equal-constant-time": { "version": "https://registry.npmjs.org/buffer-equal-constant-time/-/buffer-equal-constant-time-1.0.1.tgz", - "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=" + "integrity": "sha1-+OcRMvf/5uAaXJaXpMbz5I1cyBk=", + "dev": true }, "dom-storage": { "version": "https://registry.npmjs.org/dom-storage/-/dom-storage-2.0.2.tgz", - "integrity": "sha1-7RfL9oq9EOCu+BgnE+KXxeS1ALA=" + "integrity": "sha1-7RfL9oq9EOCu+BgnE+KXxeS1ALA=", + "dev": true }, "ecdsa-sig-formatter": { "version": "https://registry.npmjs.org/ecdsa-sig-formatter/-/ecdsa-sig-formatter-1.0.9.tgz", - "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=" + "integrity": "sha1-S8kmJ07Dtau1AW5+HWCSGsJisqE=", + "dev": true }, "faye-websocket": { "version": "https://registry.npmjs.org/faye-websocket/-/faye-websocket-0.9.3.tgz", - "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=" + "integrity": "sha1-SCpQWw3wrmJrlphm0710DNuWLoM=", + "dev": true }, "hoek": { "version": "https://registry.npmjs.org/hoek/-/hoek-2.16.3.tgz", - "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=" + "integrity": "sha1-ILt0A9POo5jpHcRxCo/xuCdKJe0=", + "dev": true }, "isemail": { "version": "https://registry.npmjs.org/isemail/-/isemail-1.2.0.tgz", - "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=" + "integrity": "sha1-vgPfjMPineTSxd9lASY/H6RZXpo=", + "dev": true }, "joi": { "version": "https://registry.npmjs.org/joi/-/joi-6.10.1.tgz", - "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=" + "integrity": "sha1-TVDDGAeRIgAP5fFq8f+OGRe3fgY=", + "dev": true }, "jsonwebtoken": { "version": "https://registry.npmjs.org/jsonwebtoken/-/jsonwebtoken-7.4.1.tgz", - "integrity": "sha1-fKMk9SFfi+A5zTWmxFu4y3SkSPs=" + "integrity": "sha1-fKMk9SFfi+A5zTWmxFu4y3SkSPs=", + "dev": true }, "jwa": { "version": "https://registry.npmjs.org/jwa/-/jwa-1.1.5.tgz", - "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=" + "integrity": "sha1-oFUs4CIHQs1S4VN3SjKQXDDnVuU=", + "dev": true }, "jws": { "version": "https://registry.npmjs.org/jws/-/jws-3.1.4.tgz", - "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=" + "integrity": "sha1-+ei5M46KhHJ31kRLFGT2GIDgUKI=", + "dev": true }, "lodash.once": { "version": "https://registry.npmjs.org/lodash.once/-/lodash.once-4.1.1.tgz", - "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=" + "integrity": "sha1-DdOXEhPHxW34gJd9UEyI+0cal6w=", + "dev": true }, "moment": { "version": "https://registry.npmjs.org/moment/-/moment-2.18.1.tgz", - "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=" + "integrity": "sha1-w2GT3Tzhwu7SrbfIAtu8d6gbHA8=", + "dev": true }, "ms": { "version": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", - "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=", + "dev": true }, "promise-polyfill": { "version": "https://registry.npmjs.org/promise-polyfill/-/promise-polyfill-6.0.2.tgz", - "integrity": "sha1-2chtPcTcLfkBboiUbe/Wm0m0EWI=" + "integrity": "sha1-2chtPcTcLfkBboiUbe/Wm0m0EWI=", + "dev": true }, "safe-buffer": { "version": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.0.tgz", - "integrity": "sha1-/kyEYDl/nqqqWOc75GJzQIpF4iM=" + "integrity": "sha1-/kyEYDl/nqqqWOc75GJzQIpF4iM=", + "dev": true }, "topo": { "version": "https://registry.npmjs.org/topo/-/topo-1.1.0.tgz", - "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=" + "integrity": "sha1-6ddRYV0buH3IZdsYL6HKCl71NtU=", + "dev": true }, "websocket-driver": { "version": "https://registry.npmjs.org/websocket-driver/-/websocket-driver-0.6.5.tgz", - "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=" + "integrity": "sha1-XLJVbOuF9Dc8bYI4qmkchFThOjY=", + "dev": true }, "websocket-extensions": { "version": "https://registry.npmjs.org/websocket-extensions/-/websocket-extensions-0.1.1.tgz", - "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=" + "integrity": "sha1-domUmcGEtu91Q3fC27DNbLVdKec=", + "dev": true }, "xmlhttprequest": { "version": "https://registry.npmjs.org/xmlhttprequest/-/xmlhttprequest-1.8.0.tgz", - "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=" + "integrity": "sha1-Z/4HXFwk/vOfnWX197f+dRcZaPw=", + "dev": true }, "xtend": { "version": "https://registry.npmjs.org/xtend/-/xtend-4.0.1.tgz", - "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=" + "integrity": "sha1-pcbVMr5lbiPbgg77lDofBJmNY68=", + "dev": true } } }, @@ -3395,7 +3423,8 @@ "hoist-non-react-statics": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/hoist-non-react-statics/-/hoist-non-react-statics-1.2.0.tgz", - "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=" + "integrity": "sha1-qkSM8JhtVcxAdzsXF0t90GbLfPs=", + "dev": true }, "home-or-tmp": { "version": "2.0.0", @@ -3544,7 +3573,8 @@ "iconv-lite": { "version": "0.4.18", "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.18.tgz", - "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==" + "integrity": "sha512-sr1ZQph3UwHTR0XftSbK85OvBbxe/abLGzEnPENCQwmHf7sck8Oyu4ob3LgBxWWxRoM+QszeUyl7jbqapu2TqA==", + "dev": true }, "icss-replace-symbols": { "version": "1.1.0", @@ -3663,7 +3693,8 @@ "invariant": { "version": "2.2.2", "resolved": "https://registry.npmjs.org/invariant/-/invariant-2.2.2.tgz", - "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=" + "integrity": "sha1-nh9WrArNtr8wMwbzOL47IErmA2A=", + "dev": true }, "invert-kv": { "version": "1.0.0", @@ -3830,7 +3861,8 @@ "is-promise": { "version": "2.1.0", "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", - "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=", + "dev": true }, "is-property": { "version": "1.0.2", @@ -3847,7 +3879,8 @@ "is-stream": { "version": "1.1.0", "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", - "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=", + "dev": true }, "is-string": { "version": "1.0.4", @@ -3906,7 +3939,8 @@ "isomorphic-fetch": { "version": "2.2.1", "resolved": "https://registry.npmjs.org/isomorphic-fetch/-/isomorphic-fetch-2.2.1.tgz", - "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=" + "integrity": "sha1-YRrhrPFPXoH3KVB0coGf6XM1WKk=", + "dev": true }, "isstream": { "version": "0.1.2", @@ -3967,7 +4001,8 @@ "js-tokens": { "version": "3.0.1", "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-3.0.1.tgz", - "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=" + "integrity": "sha1-COnxMkhKLEWjCQfp3E1VZ7fxFNc=", + "dev": true }, "js-yaml": { "version": "3.7.0", @@ -4247,12 +4282,14 @@ "lodash": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.4.tgz", - "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=" + "integrity": "sha1-eCA6TRwyiuHYbcpkYONptX9AVa4=", + "dev": true }, "lodash-es": { "version": "4.17.4", "resolved": "https://registry.npmjs.org/lodash-es/-/lodash-es-4.17.4.tgz", - "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=" + "integrity": "sha1-3MHXVS4VCgZABzupyzHXDwMpUOc=", + "dev": true }, "lodash._baseassign": { "version": "3.2.0", @@ -4391,7 +4428,8 @@ "loose-envify": { "version": "1.3.1", "resolved": "https://registry.npmjs.org/loose-envify/-/loose-envify-1.3.1.tgz", - "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=" + "integrity": "sha1-0aitM/qc4OcT1l/dCsi3SNR4yEg=", + "dev": true }, "loud-rejection": { "version": "1.6.0", @@ -4665,7 +4703,8 @@ "node-fetch": { "version": "1.7.1", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-1.7.1.tgz", - "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==" + "integrity": "sha512-j8XsFGCLw79vWXkZtMSmmLaOk9z5SQ9bV/tkbZVCqvgwzrjAGq66igobLofHtF63NvMTp2WjytpsNTGKa+XRIQ==", + "dev": true }, "node-libs-browser": { "version": "2.0.0", @@ -4768,7 +4807,8 @@ "object-assign": { "version": "4.1.1", "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", - "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=", + "dev": true }, "object-component": { "version": "0.0.3", @@ -5565,12 +5605,14 @@ "promise": { "version": "7.3.0", "resolved": "https://registry.npmjs.org/promise/-/promise-7.3.0.tgz", - "integrity": "sha512-bzAZ0u9Kxa0FYyfISjr9/PK7sCclAzc5rP4UgynMWA2Qv/gpZLKynJmTEXYq2i/giYdjBfRONDhfbsMlGIgvjA==" + "integrity": "sha512-bzAZ0u9Kxa0FYyfISjr9/PK7sCclAzc5rP4UgynMWA2Qv/gpZLKynJmTEXYq2i/giYdjBfRONDhfbsMlGIgvjA==", + "dev": true }, "prop-types": { "version": "15.5.10", "resolved": "https://registry.npmjs.org/prop-types/-/prop-types-15.5.10.tgz", - "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=" + "integrity": "sha1-J5ffwxJhguOpXj37suiT3ddFYVQ=", + "dev": true }, "proxy-addr": { "version": "1.1.4", @@ -5915,7 +5957,8 @@ "redux-form": { "version": "6.8.0", "resolved": "https://registry.npmjs.org/redux-form/-/redux-form-6.8.0.tgz", - "integrity": "sha512-rISN+EERGB8nAS/LDnOSQaTf0f+QreXEq+7pRVvBFzmH5vIsYRwVpBtYA8UsibGzO+0BL1bl5L5bxdrNwxI+sA==" + "integrity": "sha512-rISN+EERGB8nAS/LDnOSQaTf0f+QreXEq+7pRVvBFzmH5vIsYRwVpBtYA8UsibGzO+0BL1bl5L5bxdrNwxI+sA==", + "dev": true }, "redux-form-material-ui": { "version": "4.2.0", @@ -6234,7 +6277,8 @@ "setimmediate": { "version": "1.0.5", "resolved": "https://registry.npmjs.org/setimmediate/-/setimmediate-1.0.5.tgz", - "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=" + "integrity": "sha1-KQy7Iy4waULX1+qbg3Mqt4VvgoU=", + "dev": true }, "setprototypeof": { "version": "1.0.3", @@ -6716,7 +6760,8 @@ "ua-parser-js": { "version": "0.7.12", "resolved": "https://registry.npmjs.org/ua-parser-js/-/ua-parser-js-0.7.12.tgz", - "integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=" + "integrity": "sha1-BMgamb3V3FImPqKdJMa/jUgYpLs=", + "dev": true }, "uglify-js": { "version": "3.0.17", @@ -7100,7 +7145,8 @@ "whatwg-fetch": { "version": "2.0.3", "resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-2.0.3.tgz", - "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=" + "integrity": "sha1-nITsLc9oGH/wC8ZOEnS0QhduHIQ=", + "dev": true }, "whet.extend": { "version": "0.9.9", diff --git a/package.json b/package.json index 24b0cdb..3894330 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "firekit", - "version": "0.1.0", + "version": "0.1.1", "description": "Toolkit for connecting Firebase with Redux store", "main": "lib/index.js", "module": "es/index.js", @@ -18,12 +18,11 @@ "test:coverage": "nwb test-react --coverage", "test:watch": "nwb test-react --server" }, - "dependencies": { - "firebase": "^4.1.2", - "redux-form": "^6.8.0" - }, + "dependencies": {}, "peerDependencies": { - "react": "15.x" + "react": "15.x", + "firebase": "4.x", + "redux-form": "6.x" }, "devDependencies": { "firebase": "^4.1.2", diff --git a/src/index.js b/src/index.js index f6ef1c4..42b9f26 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,15 @@ +import listsReducer from './store/lists/reducer'; +import pathsReducer from './store/paths/reducer'; +import initializationReducer from './store/initialization/reducer'; +import connectionReducer from './store/connection/reducer'; + +const firekitReducers={ + lists: listsReducer, + paths: pathsReducer, + connection: connectionReducer, + initialization: initializationReducer +} + export { default as FirebaseProvider } from './components/FirebaseProvider'; export { default as FireForm } from './components/FireForm'; export { default as withFirebase } from './withFirebase'; @@ -5,3 +17,4 @@ export { default as connectionReducer } from './store/connection/reducer'; export { default as listsReducer } from './store/lists/reducer'; export { default as pathsReducer } from './store/paths/reducer'; export { default as initializationReducer } from './store/initialization/reducer'; +export default firekitReducers; diff --git a/src/store/lists/actions.js b/src/store/lists/actions.js index 4cbe8ba..df96ddc 100644 --- a/src/store/lists/actions.js +++ b/src/store/lists/actions.js @@ -52,14 +52,40 @@ const getPayload = (snapshot) => { } +const getPath = (firebaseApp, ref) => { + return ref.toString().substring(firebaseApp.database().ref().root.toString().length); +} + +const getRef = (firebaseApp, path) => { + + if (typeof path === 'string' || path instanceof String){ + return firebaseApp.database().ref(path); + }else{ + return path; + } + +} + +const getLocation = (firebaseApp, path) => { + + if (typeof path === 'string' || path instanceof String){ + return path; + }else{ + return getPath(firebaseApp, path); + } + +} + export function watchList(firebaseApp, path) { + let ref =getRef(firebaseApp, path); + let location=getLocation(firebaseApp, path); + return (dispatch, getState) => { let initialized = false; - const isInitialized=initSelectors.isInitialised(getState(), path); + const isInitialized=initSelectors.isInitialised(getState(), location); if(!isInitialized){ - const ref=firebaseApp.database().ref(path); ref.once("value", snapshot => { initialized = true; @@ -73,21 +99,21 @@ export function watchList(firebaseApp, path) { list[childKey]=childData; }); - dispatch(initialize(list, path)); + dispatch(initialize(list, location)); }); ref.on('child_added', snapshot => { if (initialized) { - dispatch(childAdded(getPayload(snapshot), path)); + dispatch(childAdded(getPayload(snapshot), location)); } }); ref.on('child_changed', snapshot => { - dispatch(childChanged(getPayload(snapshot), path)); + dispatch(childChanged(getPayload(snapshot), location)); }); ref.on('child_removed', snapshot => { - dispatch(childRemoved(getPayload(snapshot), path)); + dispatch(childRemoved(getPayload(snapshot), location)); }); } @@ -99,17 +125,24 @@ export function watchList(firebaseApp, path) { export function unwatchList(firebaseApp, path) { return dispatch => { - firebaseApp.database().ref(path).off(); - dispatch(unWatch(path)); + + let ref =getRef(firebaseApp, path); + let location=getLocation(firebaseApp, path); + + ref.off(); + dispatch(unWatch(location)); } } export function destroyList(firebaseApp, path) { return dispatch => { - firebaseApp.database().ref(path).off(); - dispatch(unWatch(path)); - dispatch(destroy(path)); + let ref =getRef(firebaseApp, path); + let location=getLocation(firebaseApp, path); + + ref.off(); + dispatch(unWatch(location)); + dispatch(destroy(location)); } }