1
0
mirror of https://github.com/chinchang/web-maker.git synced 2025-07-13 10:06:23 +02:00

Firebase is here people!

This commit is contained in:
Kushagra Gour
2018-06-02 10:57:35 +05:30
parent ba9ee64f68
commit 652b0a727d
10 changed files with 343 additions and 5 deletions

View File

@ -28,6 +28,7 @@
},
"dependencies": {
"codemirror": "^5.37.0",
"firebase": "^5.0.4",
"preact": "^8.2.6",
"preact-compat": "^3.17.0",
"preact-router": "^2.5.7"

49
webmaker/src/analytics.js Normal file
View File

@ -0,0 +1,49 @@
import {
log
} from "./utils";
/* global ga */
// eslint-disable-next-line max-params
export function trackEvent(category, action, label, value) {
if (window.DEBUG) {
log('trackevent', category, action, label, value);
return;
}
if (window.ga) {
ga('send', 'event', category, action, label, value);
}
};
// if online, load after sometime
if (navigator.onLine && !window.DEBUG) {
/* eslint-disable */
// prettier-ignore
setTimeout(function () {
(function (i, s, o, g, r, a, m) {
i['GoogleAnalyticsObject'] = r;
i[r] = i[r] || function () {
(i[r].q = i[r].q || []).push(arguments)
}, i[r].l = 1 * new Date();
a = s.createElement(o),
m = s.getElementsByTagName(o)[0];
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m)
})(window, document, 'script', 'https://www.google-analytics.com/analytics.js', 'ga');
if (location.href.indexOf('chrome-extension://') === -1) {
ga('create', 'UA-87786708-1');
} else {
ga('create', 'UA-87786708-1', {
'cookieDomain': 'none'
});
// required for chrome extension protocol
ga('set', 'checkProtocolTask', function () { /* nothing */ });
}
ga('send', 'pageview');
}, 100);
/* eslint-enable */
}

43
webmaker/src/auth.js Normal file
View File

@ -0,0 +1,43 @@
import {
trackEvent
} from './analytics';
import firebase from 'firebase/app'
export const auth = {
logout() {
firebase.auth().signOut();
},
login(providerName) {
var provider;
if (providerName === 'facebook') {
provider = new firebase.auth.FacebookAuthProvider();
} else if (providerName === 'twitter') {
provider = new firebase.auth.TwitterAuthProvider();
} else if (providerName === 'google') {
provider = new firebase.auth.GoogleAuthProvider();
provider.addScope('https://www.googleapis.com/auth/userinfo.profile');
} else {
provider = new firebase.auth.GithubAuthProvider();
}
return firebase
.auth()
.signInWithPopup(provider)
.then(function () {
trackEvent('fn', 'loggedIn', providerName);
// Save to recommend next time
window.db.local.set({
lastAuthProvider: providerName
});
})
.catch(function (error) {
utils.log(error);
if (error.code === 'auth/account-exists-with-different-credential') {
alert(
'You have already signed up with the same email using different social login'
);
}
});
}
}

View File

@ -0,0 +1,74 @@
import { h, Component } from 'preact';
import { jsLibs, cssLibs } from '../libraryList';
import { trackEvent } from '../analytics';
import { auth } from '../auth';
export default class Login extends Component {
login(e) {
const provider = e.target.dataset.authProvider;
trackEvent('ui', 'loginProviderClick', provider);
auth.login(provider);
}
logout(e) {
if (this.unsavedEditCount) {
var shouldDiscard = confirm(
'You have unsaved changes. Do you still want to logout?'
);
if (!shouldDiscard) {
return;
}
}
trackEvent('fn', 'loggedOut');
auth.logout();
}
render() {
return (
<div>
<h2>Login / Signup</h2>
<div>
<p>
<button
type="button"
onClick={this.login.bind(this)}
class="social-login-btn social-login-btn--github btn btn-icon btn--big full-width hint--right hint--always"
data-auth-provider="github"
data-hint="You logged in with Github last time"
>
<svg>
<use xlinkHref="#github-icon" />
</svg>Login with Github
</button>
</p>
<p>
<button
type="button"
onClick={this.login.bind(this)}
class="social-login-btn social-login-btn--google btn btn-icon btn--big full-width hint--right hint--always"
data-auth-provider="google"
data-hint="You logged in with Google last time"
>
<svg>
<use xlinkHref="#google-icon" />
</svg>Login with Google
</button>
</p>
<p class="mb-2">
<button
type="button"
onClick={this.login.bind(this)}
class="social-login-btn social-login-btn--facebook btn btn-icon btn--big full-width hint--right hint--always"
data-auth-provider="facebook"
data-hint="You logged in with Facebook last time"
>
<svg>
<use xlinkHref="#fb-icon" />
</svg>Login with Facebook
</button>
</p>
<p>Join a community of 50,000+ Developers</p>
</div>
</div>
);
}
}

View File

@ -94,7 +94,7 @@ export default class Header extends Component {
Open
</a>
<a
d-open-modal="loginModal"
onClick={this.props.loginBtnHandler}
data-event-category="ui"
data-event-action="loginButtonClick"
class="hide-on-login flex flex-v-center hint--rounded hint--bottom-left"
@ -103,7 +103,7 @@ export default class Header extends Component {
Login/Signup
</a>
<a
d-open-modal="profileModal"
onClick={this.props.profileBtnHandler}
data-event-category="ui"
data-event-action="headerAvatarClick"
aria-label="See profile or Logout"
@ -112,7 +112,11 @@ export default class Header extends Component {
<img
id="headerAvatarImg"
width="20"
src=""
src={
this.props.user
? this.props.user.photoURL || DEFAULT_PROFILE_IMG
: ''
}
class="main-header__avatar-img"
/>
</a>

View File

@ -0,0 +1,35 @@
import { h, Component } from 'preact';
export default class Profile extends Component {
render() {
return (
<div class="tac">
<img
height="80"
class="profile-modal__avatar-img"
src={
this.props.user
? this.props.user.photoURL || DEFAULT_PROFILE_IMG
: ''
}
id="profileAvatarImg"
alt="Profile image"
/>
<h3 id="profileUserName" class="mb-2">
{this.props.user && this.props.user.displayName
? this.props.user.displayName
: 'Anonymous Creator'}
</h3>
<p>
<button
class="btn"
aria-label="Logout from your account"
onClick={this.props.logoutBtnHandler}
>
Logout
</button>
</p>
</div>
);
}
}

View File

@ -8,6 +8,7 @@ import SavedItemPane from './SavedItemPane.jsx';
import AddLibrary from './AddLibrary.jsx';
import Modal from './Modal.jsx';
import HelpModal from './HelpModal.jsx';
import Login from './Login.jsx';
import { log, generateRandomId } from '../utils';
import { itemService } from '../itemService';
import '../db';
@ -17,6 +18,9 @@ import { modes, cssModes } from '../codeModes';
import { trackEvent } from '../analytics';
import { deferred } from '../deferred';
import { alertsService } from '../notifications';
import firebase from 'firebase/app';
import 'firebase/auth';
import Profile from './Profile';
if (module.hot) {
require('preact/debug');
@ -38,6 +42,8 @@ export default class App extends Component {
isAddLibraryModalOpen: false,
isHelpModalOpen: false,
isNotificationsModalOpen: false,
isLoginModalOpen: false,
isProfileModalOpen: false,
prefs: {},
currentItem: {
title: '',
@ -68,6 +74,45 @@ export default class App extends Component {
infiniteLoopTimeout: 1000
};
this.prefs = {};
firebase.auth().onAuthStateChanged(user => {
this.setState({ isLoginModalOpen: false });
if (user) {
log('You are -> ', user);
alertsService.add('You are now logged in!');
this.setState({ user });
window.user = user;
if (
!window.localStorage[LocalStorageKeys.ASKED_TO_IMPORT_CREATIONS] &&
window.oldSavedCreationsCountEl
) {
this.fetchItems(false, true).then(items => {
if (!items.length) {
return;
}
this.oldSavedItems = items;
// window.oldSavedCreationsCountEl.textContent = items.length;
this.setState({
isAskToImportModalOpen: true
});
trackEvent('ui', 'askToImportModalSeen');
});
}
window.db.getUser(user.uid).then(customUser => {
if (customUser) {
const prefs = { ...this.state.prefs };
Object.assign(prefs, user.settings);
this.setState({ prefs: prefs });
this.updateSetting();
}
});
} else {
this.setState({ user: undefined });
delete window.user;
// User is signed out.
}
this.updateProfileUi();
});
}
componentWillMount() {
@ -121,6 +166,14 @@ export default class App extends Component {
this.updateSetting();
});
}
updateProfileUi() {
if (this.state.user) {
document.body.classList.add('is-logged-in');
} else {
document.body.classList.remove('is-logged-in');
}
}
refreshEditor() {}
createNewItem() {
var d = new Date();
@ -561,6 +614,27 @@ export default class App extends Component {
}
autoSaveLoop() {}
loginBtnClickHandler() {
this.setState({ isLoginModalOpen: true });
}
profileBtnClickHandler() {
this.setState({ isProfileModalOpen: true });
}
logout(e) {
e.preventDefault();
if (unsavedEditCount) {
var shouldDiscard = confirm(
'You have unsaved changes. Do you still want to logout?'
);
if (!shouldDiscard) {
return;
}
}
trackEvent('fn', 'loggedOut');
window.logout();
}
render() {
return (
<div>
@ -569,10 +643,13 @@ export default class App extends Component {
externalLibCount={this.state.externalLibCount}
openBtnHandler={this.openSavedItemsPane.bind(this)}
saveBtnHandler={this.saveBtnClickHandler.bind(this)}
loginBtnHandler={this.loginBtnClickHandler.bind(this)}
profileBtnHandler={this.profileBtnClickHandler.bind(this)}
addLibraryBtnHandler={this.openAddLibrary.bind(this)}
isFetchingItems={this.state.isFetchingItems}
isSaving={this.state.isSaving}
titleInputBlurHandler={this.titleInputBlurHandler.bind(this)}
user={this.state.user}
/>
<ContentWrap
currentItem={this.state.currentItem}
@ -647,6 +724,18 @@ export default class App extends Component {
onChange={this.updateSetting.bind(this)}
/>
</Modal>
<Modal
show={this.state.isLoginModalOpen}
closeHandler={() => this.setState({ isLoginModalOpen: false })}
>
<Login />
</Modal>
<Modal
show={this.state.isProfileModalOpen}
closeHandler={() => this.setState({ isProfileModalOpen: false })}
>
<Profile user={this.state.user} />
</Modal>
<HelpModal
show={this.state.isHelpModalOpen}
closeHandler={() => this.setState({ isHelpModalOpen: false })}

View File

@ -1,6 +1,14 @@
import './firebaseInit';
import firebase from 'firebase/app';
import 'firebase/firestore';
import {
deferred
} from './deferred'
} from './deferred';
import {
trackEvent
} from './analytics';
(() => {
const FAUX_DELAY = 1;
@ -53,6 +61,10 @@ import {
.then(function () {
// Initialize Cloud Firestore through firebase
db = firebase.firestore();
// const settings = {
// timestampsInSnapshots: true
// };
// db.settings(settings);
utils.log('firebase db ready', db);
resolve(db);
})
@ -64,7 +76,7 @@ import {
alert(
"Opening Web Maker web app in multiple tabs isn't supported at present and it seems like you already have it opened in another tab. Please use in one tab."
);
window.trackEvent('fn', 'multiTabError');
trackEvent('fn', 'multiTabError');
} else if (err.code === 'unimplemented') {
// The current browser does not support all of the
// features required to enable persistence

View File

@ -0,0 +1,11 @@
import firebase from 'firebase/app';
// import 'firebase/firestore';
const config = {
apiKey: 'AIzaSyBl8Dz7ZOE7aP75mipYl2zKdLSRzBU2fFc',
authDomain: 'web-maker-app.firebaseapp.com',
databaseURL: 'https://web-maker-app.firebaseio.com',
projectId: 'web-maker-app',
storageBucket: 'web-maker-app.appspot.com',
messagingSenderId: '560473480645'
};
firebase.initializeApp(config);

View File

@ -0,0 +1,20 @@
var hideTimeout;
function addNotification(msg) {
const noticationContainerEL = $('#js-alerts-container');
// var n = document.createElement('div');
// div.textContent = msg;
// noticationContainerEL.appendChild(n);
noticationContainerEL.textContent = msg;
noticationContainerEL.classList.add('is-active');
clearTimeout(hideTimeout);
hideTimeout = setTimeout(function () {
noticationContainerEL.classList.remove('is-active');
}, 2000);
}
export const alertsService = {
add: addNotification
};