refactor: use firebase modular API
This commit is contained in:
parent
671965942a
commit
22c927e6ed
4 changed files with 69 additions and 147 deletions
|
|
@ -1,21 +0,0 @@
|
||||||
import firebase from 'firebase/app';
|
|
||||||
import 'firebase/firestore';
|
|
||||||
|
|
||||||
export class DatabaseService {
|
|
||||||
constructor() {
|
|
||||||
// necessary keys to interact with firebase
|
|
||||||
// not a secret
|
|
||||||
// https://stackoverflow.com/questions/37482366/is-it-safe-to-expose-firebase-apikey-to-the-public/37484053#37484053
|
|
||||||
const config = {
|
|
||||||
apiKey: "AIzaSyAbDzNHCSFh59e3r5sZA4_2ZHJnJ6SCCxM",
|
|
||||||
authDomain: "moment-188701.firebaseapp.com",
|
|
||||||
databaseURL: "https://moment-188701.firebaseio.com",
|
|
||||||
projectId: "secure-moment-188701",
|
|
||||||
storageBucket: "secure-moment-188701.appspot.com",
|
|
||||||
messagingSenderId: "113827947104",
|
|
||||||
appId: "1:113827947104:web:b176f746d8358302c51905"
|
|
||||||
};
|
|
||||||
firebase.initializeApp(config);
|
|
||||||
this.store = firebase.firestore();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
@ -1,4 +1,3 @@
|
||||||
export * from './database/db.js';
|
|
||||||
export * from './dialog/dialog.js';
|
export * from './dialog/dialog.js';
|
||||||
export * from './leader-board/leader-board.js';
|
export * from './leader-board/leader-board.js';
|
||||||
export * from './loading/loading.js';
|
export * from './loading/loading.js';
|
||||||
|
|
|
||||||
|
|
@ -1,43 +1,74 @@
|
||||||
import { DatabaseService } from '../database/db';
|
|
||||||
import { TimerService } from '../timer/timer';
|
import { TimerService } from '../timer/timer';
|
||||||
import { UserService } from '../user/user';
|
import { UserService } from '../user/user';
|
||||||
import { LoadingService } from '../loading/loading';
|
import { LoadingService } from '../loading/loading';
|
||||||
import { LoggerService } from '../logger/logger';
|
import { LoggerService } from '../logger/logger';
|
||||||
|
|
||||||
const dbService = new DatabaseService();
|
import { initializeApp } from 'firebase/app';
|
||||||
const timerService = new TimerService();
|
import { getFirestore, doc, getDocs, getDoc, setDoc, collection, query, orderBy, limit } from 'firebase/firestore/lite';
|
||||||
const loadingService = new LoadingService();
|
|
||||||
const loggerService = new LoggerService();
|
|
||||||
const db = dbService.store;
|
|
||||||
const user = new UserService();
|
|
||||||
let previousLevel;
|
|
||||||
|
|
||||||
export class LeaderBoardService {
|
export class LeaderBoardService {
|
||||||
constructor(leaders, all, configuration) {
|
|
||||||
this.leaders = db.collection(leaders);
|
timerService = new TimerService();
|
||||||
this.all = db.collection(all);
|
loadingService = new LoadingService();
|
||||||
db.collection(configuration)
|
loggerService = new LoggerService();
|
||||||
.doc('configuration')
|
user = new UserService();
|
||||||
.get()
|
previousLevel;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Create the Leader Board service
|
||||||
|
* @param {String} leaders
|
||||||
|
* @param {String} all
|
||||||
|
* @param {String} configuration
|
||||||
|
*/
|
||||||
|
constructor() {
|
||||||
|
|
||||||
|
// necessary keys to interact with firebase
|
||||||
|
// not a secret
|
||||||
|
// https://stackoverflow.com/questions/37482366/is-it-safe-to-expose-firebase-apikey-to-the-public/37484053#37484053
|
||||||
|
// For Firebase JS SDK v7.20.0 and later, measurementId is optional
|
||||||
|
const config = {
|
||||||
|
apiKey: "AIzaSyCTi_5Sm5dHFNf0d_Gn0MNWmlGheFBf6MQ",
|
||||||
|
authDomain: "moment-188701.firebaseapp.com",
|
||||||
|
databaseURL: "https://moment-188701.firebaseio.com",
|
||||||
|
projectId: "secure-moment-188701",
|
||||||
|
storageBucket: "secure-moment-188701.firebasestorage.app",
|
||||||
|
messagingSenderId: "113827947104",
|
||||||
|
appId: "1:113827947104:web:b176f746d8358302c51905",
|
||||||
|
measurementId: "G-LZRDY0TG46"
|
||||||
|
};
|
||||||
|
console.log('Initializing firebase app...');
|
||||||
|
const app = initializeApp(config);
|
||||||
|
this._store = getFirestore(app);
|
||||||
|
|
||||||
|
const configRef = doc(this.store, 'mw-config', 'configuration')
|
||||||
|
getDoc(configRef)
|
||||||
.then(res => {
|
.then(res => {
|
||||||
this.configuration = res.data();
|
this.configuration = res.data()
|
||||||
this.configurationPromt();
|
console.log('Received config', this.configuration)
|
||||||
})
|
})
|
||||||
.catch(err => console.error(err));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
update(level, displayElement, title) {
|
get store() {
|
||||||
if (level !== previousLevel) {
|
return this._store;
|
||||||
loadingService.addLoading(displayElement);
|
}
|
||||||
previousLevel = level;
|
|
||||||
if (this.unsubscribe) {
|
async update(level, displayElement, title) {
|
||||||
this.unsubscribe();
|
|
||||||
}
|
if (level !== this.previousLevel) {
|
||||||
|
console.log('updating leaderboard...')
|
||||||
|
this.loadingService.addLoading(displayElement);
|
||||||
|
this.previousLevel = level;
|
||||||
this.lastPlace = Number.MAX_SAFE_INTEGER;
|
this.lastPlace = Number.MAX_SAFE_INTEGER;
|
||||||
// todo: use 'where' to filter by day, week, month, and all-time
|
|
||||||
this.topList = this.leaders.doc(level)
|
const q = query(
|
||||||
.collection('games').orderBy('time').limit(10);
|
collection(this.store, "mw-leaders", level, 'games'),
|
||||||
this.unsubscribe = this.setListener(this.topList, displayElement, title);
|
orderBy('time'),
|
||||||
|
limit(10)
|
||||||
|
);
|
||||||
|
this.topListSnapshot = await getDocs(q)
|
||||||
|
this.renderList(displayElement, title, this.topListSnapshot.docs)
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
@ -66,7 +97,7 @@ export class LeaderBoardService {
|
||||||
let i = 1;
|
let i = 1;
|
||||||
docs.forEach(game => {
|
docs.forEach(game => {
|
||||||
if (game) {
|
if (game) {
|
||||||
const prettyTime = timerService.pretty(game.data().time);
|
const prettyTime = this.timerService.pretty(game.data().time);
|
||||||
const name = game.data().name || 'Anonymous';
|
const name = game.data().name || 'Anonymous';
|
||||||
const item = document.createElement('div');
|
const item = document.createElement('div');
|
||||||
item.style.display = 'flex';
|
item.style.display = 'flex';
|
||||||
|
|
@ -104,19 +135,19 @@ export class LeaderBoardService {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
setListener(collection, displayElement, title) {
|
|
||||||
return collection.onSnapshot(list => this.renderList(displayElement, title, list.docs));
|
|
||||||
}
|
|
||||||
|
|
||||||
send(game, key) {
|
async send(game, key) {
|
||||||
const sessionId = new Date().toDateString().replace(/\s/g, '_');
|
const sessionId = new Date().toDateString().replace(/\s/g, '_');
|
||||||
const gameId = new Date().toTimeString().replace(/\s/g, '_');
|
const gameId = new Date().toTimeString().replace(/\s/g, '_');
|
||||||
const data = {};
|
const data = {};
|
||||||
data[gameId] = game;
|
data[gameId] = game;
|
||||||
this.all.doc(user.browserId).collection('games').doc(sessionId).set(data, {merge: true});
|
|
||||||
|
const sessionRef = doc(this.store, 'mw-all', this.user.browserId, 'games', sessionId)
|
||||||
|
console.log('adding a session in mw-all...', data)
|
||||||
|
await setDoc(sessionRef, data, {merge: true})
|
||||||
|
|
||||||
if (this.configuration && game.status === this.configuration.passingStatus && game[key] < this.lastPlace) {
|
if (this.configuration && game.status === this.configuration.passingStatus && game[key] < this.lastPlace) {
|
||||||
|
console.log('setting score...', data)
|
||||||
let name = window.prompt(this.configuration.message);
|
let name = window.prompt(this.configuration.message);
|
||||||
if (!name) {
|
if (!name) {
|
||||||
name = 'Anonymous';
|
name = 'Anonymous';
|
||||||
|
|
@ -124,11 +155,12 @@ export class LeaderBoardService {
|
||||||
|
|
||||||
const newGame = {
|
const newGame = {
|
||||||
name,
|
name,
|
||||||
browserId: user.browserId,
|
browserId: this.user.browserId,
|
||||||
...game
|
...game
|
||||||
}
|
}
|
||||||
|
|
||||||
this.leaders.doc(game.level).collection('games').add(newGame);
|
const gameScoreRef = doc(collection(this.store, 'mw-leaders', game.level, 'games'))
|
||||||
|
await setDoc(gameScoreRef, newGame)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -1,88 +0,0 @@
|
||||||
const FileSystem = require('fs');
|
|
||||||
const path = require('path');
|
|
||||||
const MiniCssExtractPlugin = require('mini-css-extract-plugin');
|
|
||||||
const TerserJSPlugin = require('terser-webpack-plugin');
|
|
||||||
const OptimizeCSSAssetsPlugin = require('optimize-css-assets-webpack-plugin');
|
|
||||||
|
|
||||||
const env = process.env.NODE_ENV
|
|
||||||
|
|
||||||
const config = {
|
|
||||||
mode: env || 'development'
|
|
||||||
}
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
entry: {
|
|
||||||
main: './src/index.js',
|
|
||||||
},
|
|
||||||
output: {
|
|
||||||
filename: '[name].[contenthash].js',
|
|
||||||
path: path.resolve(__dirname, 'dist'),
|
|
||||||
},
|
|
||||||
optimization: {
|
|
||||||
minimizer: [new TerserJSPlugin({}), new OptimizeCSSAssetsPlugin({})],
|
|
||||||
splitChunks: {
|
|
||||||
chunks: 'all',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
plugins: [
|
|
||||||
new MiniCssExtractPlugin({
|
|
||||||
// Options similar to the same options in webpackOptions.output
|
|
||||||
// all options are optional
|
|
||||||
filename: '[name].[contenthash].css',
|
|
||||||
chunkFilename: '[id].css',
|
|
||||||
ignoreOrder: false, // Enable to remove warnings about conflicting order
|
|
||||||
}),
|
|
||||||
function() {
|
|
||||||
this.plugin('done', function(statsData) {
|
|
||||||
var stats = statsData.toJson();
|
|
||||||
|
|
||||||
if (!stats.errors.length) {
|
|
||||||
var htmlFileName = 'index.html';
|
|
||||||
var html = FileSystem.readFileSync(path.join(__dirname, htmlFileName), 'utf8');
|
|
||||||
|
|
||||||
console.log(stats.assetsByChunkName.main);
|
|
||||||
var htmlOutput = html.replace(
|
|
||||||
/vendors~main.bundle.js/i,
|
|
||||||
stats.assetsByChunkName['vendors~main']);
|
|
||||||
|
|
||||||
htmlOutput = htmlOutput.replace(
|
|
||||||
/main.bundle.css/i,
|
|
||||||
stats.assetsByChunkName.main[0]);
|
|
||||||
|
|
||||||
htmlOutput = htmlOutput.replace(
|
|
||||||
/main.bundle.js/i,
|
|
||||||
stats.assetsByChunkName.main[1]);
|
|
||||||
|
|
||||||
FileSystem.writeFileSync(
|
|
||||||
path.join(__dirname, 'dist', htmlFileName),
|
|
||||||
htmlOutput);
|
|
||||||
}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
],
|
|
||||||
module: {
|
|
||||||
|
|
||||||
rules: [
|
|
||||||
{
|
|
||||||
test: /\.css$/i,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: MiniCssExtractPlugin.loader,
|
|
||||||
},
|
|
||||||
'css-loader',
|
|
||||||
],
|
|
||||||
},
|
|
||||||
{
|
|
||||||
test: /\.(png|jpe?g|gif|ico)$/i,
|
|
||||||
use: [
|
|
||||||
{
|
|
||||||
loader: 'file-loader',
|
|
||||||
options: {
|
|
||||||
name: 'assets/[name].[ext]',
|
|
||||||
},
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
],
|
|
||||||
},
|
|
||||||
};
|
|
||||||
Loading…
Reference in a new issue