diff --git a/.vscode/launch.json b/.vscode/launch.json new file mode 100644 index 0000000..f6b35a0 --- /dev/null +++ b/.vscode/launch.json @@ -0,0 +1,15 @@ +{ + // Use IntelliSense to learn about possible attributes. + // Hover to view descriptions of existing attributes. + // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 + "version": "0.2.0", + "configurations": [ + { + "type": "chrome", + "request": "launch", + "name": "Launch Chrome against localhost", + "url": "http://localhost:3000", + "webRoot": "${workspaceFolder}" + } + ] +} \ No newline at end of file diff --git a/package.json b/package.json index c76bc60..73eab7c 100755 --- a/package.json +++ b/package.json @@ -1,8 +1,8 @@ { "name": "ra-data-firestore-client", - "version": "0.1.12", + "version": "0.2.1", "description": "Firestore Data Provider for react-admin", - "main": "build/index.js", + "main": "src/lib/index.js", "jsnext:main": "es/index.js", "module": "es/index.js", "directories": { @@ -27,7 +27,8 @@ "demo": "node scripts/start.js", "init": "npm run build && npm link && npm link ra-data-firestore-client", "reset": "rm -rf node_modules && rm -rf package-lock.json && npm install && npm run init", - "start": "concurrently --kill-others \"npm run build:watch\" \"npm run app-start\"" + "start": "concurrently --kill-others \"npm run build:watch\" \"npm run demo\"", + "dev":"react-scripts start" }, "author": "Rafal Zawadzki (http://rafalzawadzki.com/)", "license": "ISC", @@ -93,9 +94,9 @@ "dependencies": { "firebase": "^6.6.1", "prop-types": "^15.7.2", - "react": "16.9.0", - "react-admin": "^2.9.6", - "react-dom": "^16.9.0", + "react": "^16.10.2", + "react-admin": "3.0.0-beta.0", + "react-dom": "^16.10.2", "sort-by": "^1.2.0" } } diff --git a/src/demo/App.js b/src/demo/App.js index 0057d25..9bf6aa4 100755 --- a/src/demo/App.js +++ b/src/demo/App.js @@ -1,20 +1,27 @@ import React from 'react'; import { Admin, Resource } from 'react-admin'; -import { RestProvider, AuthProvider, base64Uploader } from '../lib'; +import { + RestProvider, + AuthProvider, + // base64Uploader, + storageUploader +} from '../lib'; -import { PostList, PostEdit, PostCreate } from './Posts'; -import { UserList, UserEdit, UserCreate } from './Users'; +import { ArticleList, ArticleEdit, ArticleCreate } from './Articles'; const firebaseConfig = { - apiKey: 'AIzaSyASpb1daoPZdpzY_-d1mkzgO-sxoBw6i9o', - authDomain: 'react-admin-firestore-client.firebaseapp.com', - databaseURL: 'https://react-admin-firestore-client.firebaseio.com', - projectId: 'react-admin-firestore-client', - storageBucket: '', - messagingSenderId: '796768771332' + apiKey: 'AIzaSyAF0MOEZ6GppP620lBcJNJt5yJL8YuaPBE', + authDomain: 'react-admin-firebase-ed1c2.firebaseapp.com', + databaseURL: 'https://react-admin-firebase-ed1c2.firebaseio.com', + projectId: 'react-admin-firebase-ed1c2', + storageBucket: 'react-admin-firebase-ed1c2.appspot.com', + messagingSenderId: '1025840448802', + appId: '1:1025840448802:web:d210968b17200f77ce117b', + measurementId: 'G-LEHM5781PT', + storagePath: 'image' }; -const trackedResources = [{ name: 'posts', isPublic: true }, { name: 'users', isPublic: true }]; +const trackedResources = [{ name: 'articles', isPublic: true }, { name: 'users', isPublic: true }]; const authConfig = { userProfilePath: '/users/', @@ -23,11 +30,11 @@ const authConfig = { // to run this demo locally, please feel free to disable authProvider to bypass login page -const dataProvider = base64Uploader(RestProvider(firebaseConfig, { trackedResources })); +const dataProvider = storageUploader(RestProvider(firebaseConfig, { trackedResources })); const App = () => ( - - + ); + export default App; diff --git a/src/demo/Users.js b/src/demo/Articles.js old mode 100755 new mode 100644 similarity index 51% rename from src/demo/Users.js rename to src/demo/Articles.js index 5096837..9d67213 --- a/src/demo/Users.js +++ b/src/demo/Articles.js @@ -12,42 +12,35 @@ import { ImageField } from 'react-admin'; -export const UserList = props => ( - +export const ArticleList = props => ( + - - - + ); -export const UserCreate = props => ( - +export const ArticleEdit = props => ( + - - - - + + - + ); -export const UserEdit = props => ( - +export const ArticleCreate = props => ( + - - - - - + + - + ); diff --git a/src/demo/Posts.js b/src/demo/Posts.js deleted file mode 100755 index ca0a29f..0000000 --- a/src/demo/Posts.js +++ /dev/null @@ -1,60 +0,0 @@ -import React from 'react'; -import { - List, - Edit, - Create, - Datagrid, - ReferenceField, - TextField, - EditButton, - DisabledInput, - LongTextInput, - ReferenceInput, - SelectInput, - SimpleForm, - TextInput, - ImageInput, - ImageField -} from 'react-admin'; - -export const PostList = props => ( - - - - - - - - - - - -); - -export const PostEdit = props => ( - - - - - - - - - - - - - -); - -export const PostCreate = props => ( - - - - - - - - - -); diff --git a/src/lib/Base64Uploader.js b/src/lib/Base64Uploader.js index 5bf281b..4573f16 100755 --- a/src/lib/Base64Uploader.js +++ b/src/lib/Base64Uploader.js @@ -8,7 +8,7 @@ const convertFileToBase64 = file => }); const addUploadFeature = requestHandler => (type, resource, params) => { - if (type === 'UPDATE') { + if (type === 'UPDATE' || type === 'CREATE') { if (params.data.image && params.data.image.length) { const formerPictures = params.data.image.filter(p => !(p.rawFile instanceof File)); const newPictures = params.data.image.filter(p => p.rawFile instanceof File); diff --git a/src/lib/RestProvider.js b/src/lib/RestProvider.js index dc7c935..22328a2 100755 --- a/src/lib/RestProvider.js +++ b/src/lib/RestProvider.js @@ -34,6 +34,9 @@ const RestProvider = (firebaseConfig = {}, options = {}) => { firebase.auth().setPersistence(firebase.auth.Auth.Persistence.SESSION); } + // const storage = firebase.storage(); + // const storageRoot = storage.ref(); + /* Functions */ const upload = options.upload || Methods.upload; const save = options.save || Methods.save; diff --git a/src/lib/StorageUploader.js b/src/lib/StorageUploader.js new file mode 100644 index 0000000..778ae4f --- /dev/null +++ b/src/lib/StorageUploader.js @@ -0,0 +1,38 @@ +const uploadFileToStorage = file => + new Promise((resolve, reject) => { + const reader = new FileReader(); + reader.readAsDataURL(file.rawFile); + + reader.onload = () => resolve(reader.result); + reader.onerror = reject; + }); + +const storageUploadFeature = requestHandler => (type, resource, params) => { + if (type === 'UPDATE' || type === 'CREATE') { + if (params.data.image && params.data.image.length) { + const formerPictures = params.data.image.filter(p => !(p.rawFile instanceof File)); + const newPictures = params.data.image.filter(p => p.rawFile instanceof File); + + return Promise.all(newPictures.map(uploadFileToStorage)) + .then(base64Pictures => + base64Pictures.map(image64 => ({ + src: image64, + title: `${params.data.title}` + })) + ) + .then(transformedNewPictures => + requestHandler(type, resource, { + ...params, + data: { + ...params.data, + image: [...transformedNewPictures, ...formerPictures] + } + }) + ); + } + } + // for other request types and reources, fall back to the defautl request handler + return requestHandler(type, resource, params); +}; + +export default storageUploadFeature; diff --git a/src/lib/index.js b/src/lib/index.js index 404ee42..f2cd86f 100755 --- a/src/lib/index.js +++ b/src/lib/index.js @@ -2,5 +2,6 @@ import RestProvider from './RestProvider'; import AuthProvider from './AuthProvider'; import * as RAFirebaseMethods from './methods'; import base64Uploader from './Base64Uploader'; +import storageUploader from './StorageUploader'; -export { RestProvider, AuthProvider, RAFirebaseMethods, base64Uploader }; +export { RestProvider, AuthProvider, RAFirebaseMethods, base64Uploader, storageUploader }; diff --git a/src/lib/methods.js b/src/lib/methods.js index c270d2a..d5f511a 100755 --- a/src/lib/methods.js +++ b/src/lib/methods.js @@ -3,7 +3,7 @@ import 'firebase/firestore'; import 'firebase/storage'; import sortBy from 'sort-by'; import { CREATE } from 'react-admin'; - +/* const convertFileToBase64 = file => new Promise((resolve, reject) => { const reader = new FileReader(); @@ -40,7 +40,7 @@ const addUploadFeature = requestHandler => (type, resource, params) => { // for other request types and reources, fall back to the defautl request handler return requestHandler(type, resource, params); }; - +*/ const getImageSize = file => { return new Promise(resolve => { const img = document.createElement('img'); @@ -266,7 +266,9 @@ export default { getOne, getList, getMany, - getManyReference, - addUploadFeature, - convertFileToBase64 + getManyReference + // addUploadFeature, + // convertFileToBase64, + // storageUploadFeature, + // uploadFileToStorage };