diff --git a/src/modules/database/db.js b/src/modules/database/db.js deleted file mode 100644 index f3bf61e..0000000 --- a/src/modules/database/db.js +++ /dev/null @@ -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(); - } -} \ No newline at end of file diff --git a/src/modules/index.js b/src/modules/index.js index 94a74d0..50b03da 100644 --- a/src/modules/index.js +++ b/src/modules/index.js @@ -1,4 +1,3 @@ -export * from './database/db.js'; export * from './dialog/dialog.js'; export * from './leader-board/leader-board.js'; export * from './loading/loading.js'; diff --git a/src/modules/leader-board/leader-board.js b/src/modules/leader-board/leader-board.js index 2b59d15..cd2e6d5 100644 --- a/src/modules/leader-board/leader-board.js +++ b/src/modules/leader-board/leader-board.js @@ -1,43 +1,74 @@ -import { DatabaseService } from '../database/db'; import { TimerService } from '../timer/timer'; import { UserService } from '../user/user'; import { LoadingService } from '../loading/loading'; import { LoggerService } from '../logger/logger'; -const dbService = new DatabaseService(); -const timerService = new TimerService(); -const loadingService = new LoadingService(); -const loggerService = new LoggerService(); -const db = dbService.store; -const user = new UserService(); -let previousLevel; +import { initializeApp } from 'firebase/app'; +import { getFirestore, doc, getDocs, getDoc, setDoc, collection, query, orderBy, limit } from 'firebase/firestore/lite'; + export class LeaderBoardService { - constructor(leaders, all, configuration) { - this.leaders = db.collection(leaders); - this.all = db.collection(all); - db.collection(configuration) - .doc('configuration') - .get() + + timerService = new TimerService(); + loadingService = new LoadingService(); + loggerService = new LoggerService(); + user = new UserService(); + 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 => { - this.configuration = res.data(); - this.configurationPromt(); + this.configuration = res.data() + console.log('Received config', this.configuration) }) - .catch(err => console.error(err)); } - update(level, displayElement, title) { - if (level !== previousLevel) { - loadingService.addLoading(displayElement); - previousLevel = level; - if (this.unsubscribe) { - this.unsubscribe(); - } + get store() { + return this._store; + } + + async update(level, displayElement, title) { + + if (level !== this.previousLevel) { + console.log('updating leaderboard...') + this.loadingService.addLoading(displayElement); + this.previousLevel = level; this.lastPlace = Number.MAX_SAFE_INTEGER; - // todo: use 'where' to filter by day, week, month, and all-time - this.topList = this.leaders.doc(level) - .collection('games').orderBy('time').limit(10); - this.unsubscribe = this.setListener(this.topList, displayElement, title); + + const q = query( + collection(this.store, "mw-leaders", level, 'games'), + 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; docs.forEach(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 item = document.createElement('div'); 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 gameId = new Date().toTimeString().replace(/\s/g, '_'); const data = {}; 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) { + console.log('setting score...', data) let name = window.prompt(this.configuration.message); if (!name) { name = 'Anonymous'; @@ -124,11 +155,12 @@ export class LeaderBoardService { const newGame = { name, - browserId: user.browserId, + browserId: this.user.browserId, ...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) } } diff --git a/webpack.config.js b/webpack.config.js deleted file mode 100644 index 4ab861a..0000000 --- a/webpack.config.js +++ /dev/null @@ -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]', - }, - }, - ], - }, - ], - }, - }; \ No newline at end of file