Compare commits
6 Commits
fc643c6388
...
391f2734d8
Author | SHA1 | Date |
---|---|---|
|
391f2734d8 | |
|
d2c0c289ab | |
|
8f9fe6e97d | |
|
0e956f6c67 | |
|
3bfaf5f3df | |
|
2cfa08abe3 |
|
@ -1,4 +1,4 @@
|
||||||
export const appListeners = (app, state, emitter) => {
|
const appListeners = (app, state, emitter) => {
|
||||||
emitter.on(state.events.DOMCONTENTLOADED, () => {
|
emitter.on(state.events.DOMCONTENTLOADED, () => {
|
||||||
emitter.emit(state.events.DOMTITLECHANGE, app.siteConfig.siteName);
|
emitter.emit(state.events.DOMTITLECHANGE, app.siteConfig.siteName);
|
||||||
|
|
||||||
|
@ -53,10 +53,14 @@ export const appListeners = (app, state, emitter) => {
|
||||||
}).then(result => callback(result));
|
}).then(result => callback(result));
|
||||||
});
|
});
|
||||||
|
|
||||||
state.i18n.fetchLocaleUI().then(() => {
|
if (state.isFrontend) {
|
||||||
app.checkIfLoggedIn(state).then(isLoggedIn => {
|
state.i18n.fetchLocaleUI().then(() => {
|
||||||
emitter.emit(state.events.RENDER); // This should hopefully only run once after the DOM is loaded. It prevents routing issues where 'render' hasn't been defined yet
|
app.checkIfLoggedIn(state).then(isLoggedIn => {
|
||||||
|
emitter.emit(state.events.RENDER); // This should hopefully only run once after the DOM is loaded. It prevents routing issues where 'render' hasn't been defined yet
|
||||||
|
});
|
||||||
});
|
});
|
||||||
})
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { appListeners };
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
import { globalView } from './views/global';
|
const { globalView } = require('./views/global');
|
||||||
import { homeView } from './views/home';
|
const { homeView } = require('./views/home');
|
||||||
import { aboutView } from './views/about';
|
const { aboutView } = require('./views/about');
|
||||||
import { loginView } from './views/login';
|
const { loginView } = require('./views/login');
|
||||||
import { searchView } from './views/search';
|
const { searchView } = require('./views/search');
|
||||||
import { shelvesView } from './views/shelves';
|
const { shelvesView } = require('./views/shelves');
|
||||||
import { errorView } from './views/404';
|
const { errorView } = require('./views/404');
|
||||||
|
|
||||||
export const appRoutes = (app) => {
|
const appRoutes = (app) => {
|
||||||
app.route('/', (state, emit) => globalView(state, emit, homeView));
|
app.route('/', (state, emit) => globalView(state, emit, homeView));
|
||||||
|
|
||||||
app.route('/about', (state, emit) => globalView(state, emit, aboutView));
|
app.route('/about', (state, emit) => globalView(state, emit, aboutView));
|
||||||
|
@ -21,3 +21,5 @@ export const appRoutes = (app) => {
|
||||||
|
|
||||||
app.route('/404', (state, emit) => globalView(state, emit, errorView));
|
app.route('/404', (state, emit) => globalView(state, emit, errorView));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { appRoutes };
|
||||||
|
|
|
@ -1,11 +1,17 @@
|
||||||
import { I18n } from "./i18n";
|
const { I18n } = require("./i18n");
|
||||||
|
|
||||||
|
const appState = (app, state, emitter) => {
|
||||||
|
state.isFrontend = typeof window !== 'undefined';
|
||||||
|
|
||||||
export const appState = (app, state, emitter) => {
|
|
||||||
state.events.SET_LANGUAGE = 'setLanguage';
|
state.events.SET_LANGUAGE = 'setLanguage';
|
||||||
state.events.ADD_TO_SHELF = 'addToShelf';
|
state.events.ADD_TO_SHELF = 'addToShelf';
|
||||||
|
|
||||||
state.language = app.getSettingsItem('lang') ? app.getSettingsItem('lang') : (navigator.language || navigator.userLanguage).split('-')[0];
|
if (state.isFrontend) {
|
||||||
|
state.language = app.getSettingsItem('lang') ? app.getSettingsItem('lang') : (window.navigator.language || window.navigator.userLanguage).split('-')[0];
|
||||||
|
state.isLoggedIn = false;
|
||||||
|
state.i18n = new I18n(state); // Global I18n class passed to all views
|
||||||
|
}
|
||||||
state.viewStates = {};
|
state.viewStates = {};
|
||||||
state.isLoggedIn = false;
|
|
||||||
state.i18n = new I18n(state); // Global I18n class passed to all views
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { appState };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
export const appUtilities = (app) => {
|
const appUtilities = (app) => {
|
||||||
app.getSettingsItem = settingsKey => {
|
app.getSettingsItem = settingsKey => {
|
||||||
let savedSettings = window.localStorage.getItem('settings');
|
let savedSettings = app.state.isFrontend && window.localStorage.getItem('settings');
|
||||||
if (savedSettings) {
|
if (savedSettings) {
|
||||||
savedSettings = JSON.parse(savedSettings);
|
savedSettings = JSON.parse(savedSettings);
|
||||||
if (typeof savedSettings[settingsKey] !== 'undefined') {
|
if (typeof savedSettings[settingsKey] !== 'undefined') {
|
||||||
|
@ -10,6 +10,8 @@ export const appUtilities = (app) => {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
app.setSettingsItem = (settingsKey, value) => {
|
app.setSettingsItem = (settingsKey, value) => {
|
||||||
|
if (!app.state.isFrontend) return null;
|
||||||
|
|
||||||
let savedSettings = window.localStorage.getItem('settings');
|
let savedSettings = window.localStorage.getItem('settings');
|
||||||
if (savedSettings) {
|
if (savedSettings) {
|
||||||
savedSettings = JSON.parse(savedSettings);
|
savedSettings = JSON.parse(savedSettings);
|
||||||
|
@ -21,6 +23,8 @@ export const appUtilities = (app) => {
|
||||||
}
|
}
|
||||||
|
|
||||||
app.checkIfLoggedIn = (appState) => {
|
app.checkIfLoggedIn = (appState) => {
|
||||||
|
if (!app.state.isFrontend) return false;
|
||||||
|
|
||||||
return fetch('/api/account/validate', { method: 'post' })
|
return fetch('/api/account/validate', { method: 'post' })
|
||||||
.then(response => response.json())
|
.then(response => response.json())
|
||||||
.then(response => {
|
.then(response => {
|
||||||
|
@ -35,3 +39,5 @@ export const appUtilities = (app) => {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { appUtilities };
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export class I18n {
|
class I18n {
|
||||||
constructor(appState) {
|
constructor(appState) {
|
||||||
this.appState = appState;
|
this.appState = appState;
|
||||||
this.availableLanguages = null;
|
this.availableLanguages = null;
|
||||||
|
@ -56,6 +56,7 @@ export class I18n {
|
||||||
}, Object.assign({}, language));
|
}, Object.assign({}, language));
|
||||||
|
|
||||||
if (translation === false) {
|
if (translation === false) {
|
||||||
|
console.log(this);
|
||||||
if (language.locale !== this.default.locale) {
|
if (language.locale !== this.default.locale) {
|
||||||
console.warn(`The translation for "${target}" is not set in the ${this.language.locale} locale. Using ${this.default.name} (${this.default.locale}) instead.`);
|
console.warn(`The translation for "${target}" is not set in the ${this.language.locale} locale. Using ${this.default.name} (${this.default.locale}) instead.`);
|
||||||
return this.translate(target, true);
|
return this.translate(target, true);
|
||||||
|
@ -71,3 +72,5 @@ export class I18n {
|
||||||
return this.translate(translation);
|
return this.translate(translation);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { I18n };
|
||||||
|
|
62
app/index.js
62
app/index.js
|
@ -1,33 +1,43 @@
|
||||||
import 'babel-polyfill';
|
require('babel-polyfill');
|
||||||
|
|
||||||
import choo from 'choo';
|
const choo = require('choo');
|
||||||
|
|
||||||
import config from './config.json';
|
const config = require('./config.json');
|
||||||
import { appRoutes } from './appRoutes';
|
const { appRoutes } = require('./appRoutes');
|
||||||
import { appListeners } from './appListeners';
|
const { appListeners } = require('./appListeners');
|
||||||
import { appState } from './appState.js';
|
const { appState } = require('./appState.js');
|
||||||
import { appUtilities } from './appUtilities.js';
|
const { appUtilities } = require('./appUtilities.js');
|
||||||
|
|
||||||
const app = choo();
|
function frontend() {
|
||||||
|
const app = choo();
|
||||||
|
|
||||||
if (process.env.NODE_ENV !== 'production') {
|
if (process.env.NODE_ENV !== 'production') {
|
||||||
// Only runs in development and will be stripped from production build.
|
// Only runs in development and will be stripped from production build.
|
||||||
app.use(require('choo-devtools')()); // Exposes `choo` to the console for debugging!
|
app.use(require('choo-devtools')()); // Exposes `choo` to the console for debugging!
|
||||||
|
}
|
||||||
|
|
||||||
|
app.use((state, emitter) => {
|
||||||
|
app.siteConfig = config;
|
||||||
|
appUtilities(app);
|
||||||
|
});
|
||||||
|
|
||||||
|
app.use((state, emitter) => {
|
||||||
|
appState(app, state);
|
||||||
|
|
||||||
|
// Listeners
|
||||||
|
appListeners(app, state, emitter);
|
||||||
|
});
|
||||||
|
|
||||||
|
// Routes
|
||||||
|
appRoutes(app);
|
||||||
|
|
||||||
|
app.mount('body'); // Overwrite the `<body>` tag with the content of the Choo app
|
||||||
|
|
||||||
|
return app;
|
||||||
}
|
}
|
||||||
|
|
||||||
app.use((state, emitter) => {
|
if (typeof window !== 'undefined') {
|
||||||
app.siteConfig = config;
|
frontend();
|
||||||
appUtilities(app);
|
}
|
||||||
});
|
|
||||||
|
|
||||||
app.use((state, emitter) => {
|
module.exports = frontend;
|
||||||
appState(app, state);
|
|
||||||
|
|
||||||
// Listeners
|
|
||||||
appListeners(app, state, emitter);
|
|
||||||
});
|
|
||||||
|
|
||||||
// Routes
|
|
||||||
appRoutes(app);
|
|
||||||
|
|
||||||
app.mount('body'); // Overwrite the `<body>` tag with the content of the Choo app
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
export const errorView = (state, emit, i18n) => {
|
const errorView = (state, emit, i18n) => {
|
||||||
return html`<section class="error card">
|
return html`<section class="error card">
|
||||||
<header>
|
<header>
|
||||||
<h1>${i18n.__('404.header')}</h1>
|
<h1>${i18n.__('404.header')}</h1>
|
||||||
|
@ -10,3 +10,5 @@ export const errorView = (state, emit, i18n) => {
|
||||||
</footer>
|
</footer>
|
||||||
</section>`;
|
</section>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { errorView };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
export const aboutView = (state, emit, i18n) => {
|
const aboutView = (state, emit, i18n) => {
|
||||||
const content = html`<section class="content"><i class="icon-loading animate-spin"></i></section>`;
|
const content = html`<section class="content"><i class="icon-loading animate-spin"></i></section>`;
|
||||||
const community = html`<section class="content"></section>`;
|
const community = html`<section class="content"></section>`;
|
||||||
|
|
||||||
|
@ -20,3 +20,5 @@ export const aboutView = (state, emit, i18n) => {
|
||||||
community,
|
community,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { aboutView };
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
export class ViewController {
|
class ViewController {
|
||||||
constructor(state, i18n, viewName, defaultState = {}) {
|
constructor(state, i18n, viewName, defaultState = {}) {
|
||||||
// Store the global app state so it's accessible but out of the way.
|
// Store the global app state so it's accessible but out of the way.
|
||||||
this.appState = state;
|
this.appState = state;
|
||||||
|
@ -16,3 +16,5 @@ export class ViewController {
|
||||||
return this.appState.isLoggedIn;
|
return this.appState.isLoggedIn;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { ViewController };
|
||||||
|
|
|
@ -1,10 +1,23 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import headerImage from '../../dev/images/header.png';
|
let headerImage;
|
||||||
|
|
||||||
export const globalView = (state, emit, view) => {
|
if (typeof window !== 'undefined') {
|
||||||
|
// Make Parcel bundler process image
|
||||||
|
headerImage = require('../../dev/images/header.png');
|
||||||
|
} else {
|
||||||
|
// Make server get processed image path
|
||||||
|
const fs = require('fs');
|
||||||
|
const path = require('path');
|
||||||
|
const publicPath = path.resolve('public');
|
||||||
|
const publicFiles = fs.readdirSync(publicPath);
|
||||||
|
const headerImageFileName = publicFiles.find(fileName => /header\..+?\.png/.test(fileName));
|
||||||
|
headerImage = path.relative(publicPath, path.resolve(publicPath, headerImageFileName));
|
||||||
|
}
|
||||||
|
|
||||||
|
const globalView = (state, emit, view) => {
|
||||||
const { i18n } = state;
|
const { i18n } = state;
|
||||||
if (i18n.needsFetch) {
|
if (state.isFrontend && i18n.needsFetch) {
|
||||||
return html`<body><i class="icon-loading animate-spin"></i></body>`;
|
return html`<body><i class="icon-loading animate-spin"></i></body>`;
|
||||||
}
|
}
|
||||||
// Create a wrapper for view content that includes global header/footer
|
// Create a wrapper for view content that includes global header/footer
|
||||||
|
@ -71,3 +84,5 @@ export const globalView = (state, emit, view) => {
|
||||||
</footer>
|
</footer>
|
||||||
</body>`;
|
</body>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { globalView };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ViewController } from '../controller';
|
const { ViewController } = require('../controller');
|
||||||
|
|
||||||
export class HomeController extends ViewController {
|
class HomeController extends ViewController {
|
||||||
constructor(state, i18n) {
|
constructor(state, i18n) {
|
||||||
// Super passes state, view name, and default state to ViewController,
|
// Super passes state, view name, and default state to ViewController,
|
||||||
// which stores state in this.appState and the view controller's state to this.state
|
// which stores state in this.appState and the view controller's state to this.state
|
||||||
|
@ -20,3 +20,5 @@ export class HomeController extends ViewController {
|
||||||
// or use `onclick=${() => controller.submit()}` to maintain the 'this' of the class instead.
|
// or use `onclick=${() => controller.submit()}` to maintain the 'this' of the class instead.
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { HomeController }
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { HomeController } from './controller'; // The controller for this view, where processing should happen.
|
const { HomeController } = require('./controller'); // The controller for this view, where processing should happen.
|
||||||
import { loggedOutView } from './loggedOut';
|
const { loggedOutView } = require('./loggedOut');
|
||||||
import { loggedInView } from './loggedIn';
|
const { loggedInView } = require('./loggedIn');
|
||||||
|
|
||||||
// This is the view function that is exported and used in the view manager.
|
// This is the view function that is exported and used in the view manager.
|
||||||
export const homeView = (state, emit, i18n) => {
|
const homeView = (state, emit, i18n) => {
|
||||||
const controller = new HomeController(state, i18n);
|
const controller = new HomeController(state, i18n);
|
||||||
|
|
||||||
// Returning an array in a view allows non-shared parent HTML elements.
|
// Returning an array in a view allows non-shared parent HTML elements.
|
||||||
|
@ -17,3 +17,5 @@ export const homeView = (state, emit, i18n) => {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { homeView };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
export const loggedInView = (homeController, emit) => {
|
const loggedInView = (homeController, emit) => {
|
||||||
const { __ } = homeController.i18n;
|
const { __ } = homeController.i18n;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -37,3 +37,5 @@ export const loggedInView = (homeController, emit) => {
|
||||||
</section>`,
|
</section>`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { loggedInView };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
export const loggedOutView = (homeController, emit) => {
|
const loggedOutView = (homeController, emit) => {
|
||||||
const { __ } = homeController.i18n;
|
const { __ } = homeController.i18n;
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
@ -81,3 +81,5 @@ export const loggedOutView = (homeController, emit) => {
|
||||||
</section>`,
|
</section>`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { loggedOutView };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ViewController } from '../controller';
|
const { ViewController } = require('../controller');
|
||||||
|
|
||||||
export class LoginController extends ViewController {
|
class LoginController extends ViewController {
|
||||||
constructor(state, emit, i18n) {
|
constructor(state, emit, i18n) {
|
||||||
// Super passes state, view name, and default state to ViewController,
|
// Super passes state, view name, and default state to ViewController,
|
||||||
// which stores state in this.appState and the view controller's state to this.state
|
// which stores state in this.appState and the view controller's state to this.state
|
||||||
|
@ -179,3 +179,5 @@ export class LoginController extends ViewController {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { LoginController };
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { LoginController } from './controller';
|
const { LoginController } = require('./controller');
|
||||||
|
|
||||||
export const loginView = (state, emit, i18n) => {
|
const loginView = (state, emit, i18n) => {
|
||||||
const controller = new LoginController(state, emit, i18n);
|
const controller = new LoginController(state, emit, i18n);
|
||||||
const { __ } = controller.i18n;
|
const { __ } = controller.i18n;
|
||||||
|
|
||||||
|
@ -165,3 +165,5 @@ export const loginView = (state, emit, i18n) => {
|
||||||
|
|
||||||
</section>`;
|
</section>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { loginView };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
export const modal = (modalId, controller, contentHTML, options = {}) => {
|
const modal = (modalId, controller, contentHTML, options = {}) => {
|
||||||
/* Options:
|
/* Options:
|
||||||
* controller <class>: Pass the controller class with state; Requires get/set for openModal in state.
|
* controller <class>: Pass the controller class with state; Requires get/set for openModal in state.
|
||||||
* buttonHTML <choo/html>: Displayed in place of the default button to open the modal
|
* buttonHTML <choo/html>: Displayed in place of the default button to open the modal
|
||||||
|
@ -77,3 +77,5 @@ export const modal = (modalId, controller, contentHTML, options = {}) => {
|
||||||
</div>`,
|
</div>`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { modal };
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { starRating } from './starRating';
|
const { starRating } = require('./starRating');
|
||||||
|
|
||||||
export const reviewCard = (controller, review) => {
|
const reviewCard = (controller, review) => {
|
||||||
const { __ } = controller.i18n;
|
const { __ } = controller.i18n;
|
||||||
|
|
||||||
return html`<article class="card">
|
return html`<article class="card">
|
||||||
|
@ -27,3 +27,5 @@ export const reviewCard = (controller, review) => {
|
||||||
</footer>
|
</footer>
|
||||||
</article>`;
|
</article>`;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { reviewCard };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
export const starRating = (rating) => {
|
const starRating = (rating) => {
|
||||||
const wholeStars = Math.floor(rating);
|
const wholeStars = Math.floor(rating);
|
||||||
const hasPartial = rating - wholeStars > 0;
|
const hasPartial = rating - wholeStars > 0;
|
||||||
const emptyStars = 5 - wholeStars - (hasPartial ? 1 : 0);
|
const emptyStars = 5 - wholeStars - (hasPartial ? 1 : 0);
|
||||||
|
@ -17,3 +17,5 @@ export const starRating = (rating) => {
|
||||||
|
|
||||||
return stars;
|
return stars;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { starRating };
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import { ViewController } from '../controller';
|
const { ViewController } = require('../controller');
|
||||||
import { ShelvesController } from '../shelves/controller';
|
const { ShelvesController } = require('../shelves/controller');
|
||||||
|
|
||||||
export class SearchController extends ViewController {
|
class SearchController extends ViewController {
|
||||||
constructor(state, emit, i18n) {
|
constructor(state, emit, i18n) {
|
||||||
// Super passes state, view name, and default state to ViewController,
|
// Super passes state, view name, and default state to ViewController,
|
||||||
// which stores state in this.appState and the view controller's state to this.state
|
// which stores state in this.appState and the view controller's state to this.state
|
||||||
|
@ -33,7 +33,8 @@ export class SearchController extends ViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
get hasQuery() {
|
get hasQuery() {
|
||||||
return this.appState.query.hasOwnProperty('for') && this.appState.query.for.trim() !== '';
|
return this.appState.isFrontend
|
||||||
|
&& this.appState.query.hasOwnProperty('for') && this.appState.query.for.trim() !== '';
|
||||||
}
|
}
|
||||||
|
|
||||||
get queryIsNew() {
|
get queryIsNew() {
|
||||||
|
@ -156,3 +157,5 @@ export class SearchController extends ViewController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { SearchController };
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { SearchController } from './controller'; // The controller for this view, where processing should happen.
|
const { SearchController } = require('./controller'); // The controller for this view, where processing should happen.
|
||||||
import { resultDetails } from './resultDetails';
|
const { resultDetails } = require('./resultDetails');
|
||||||
import { modal } from '../partials/modal';
|
const { modal } = require('../partials/modal');
|
||||||
|
|
||||||
// This is the view function that is exported and used in the view manager.
|
// This is the view function that is exported and used in the view manager.
|
||||||
export const searchView = (state, emit, i18n) => {
|
const searchView = (state, emit, i18n) => {
|
||||||
const controller = new SearchController(state, emit, i18n);
|
const controller = new SearchController(state, emit, i18n);
|
||||||
const { __ } = controller.i18n;
|
const { __ } = controller.i18n;
|
||||||
|
|
||||||
|
@ -157,3 +157,5 @@ export const searchView = (state, emit, i18n) => {
|
||||||
</section>`,
|
</section>`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { searchView };
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { reviewCard } from '../partials/reviewCard';
|
const { reviewCard } = require('../partials/reviewCard');
|
||||||
import { starRating } from '../partials/starRating';
|
const { starRating } = require('../partials/starRating');
|
||||||
import { modal } from '../partials/modal';
|
const { modal } = require('../partials/modal');
|
||||||
|
|
||||||
export const resultDetails = (searchController, result, emit = () => {}) => {
|
const resultDetails = (searchController, result, emit = () => {}) => {
|
||||||
const { __ } = searchController.i18n;
|
const { __ } = searchController.i18n;
|
||||||
const source = result.sources[0];
|
const source = result.sources[0];
|
||||||
const modalId = `result_${source.uri}`;
|
const modalId = `result_${source.uri}`;
|
||||||
|
@ -121,3 +121,5 @@ export const resultDetails = (searchController, result, emit = () => {}) => {
|
||||||
onShow,
|
onShow,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { resultDetails };
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { ViewController } from '../controller';
|
const { ViewController } = require('../controller');
|
||||||
|
|
||||||
export class ShelvesController extends ViewController {
|
class ShelvesController extends ViewController {
|
||||||
constructor(state, i18n) {
|
constructor(state, i18n) {
|
||||||
// Super passes state, view name, and default state to ViewController,
|
// Super passes state, view name, and default state to ViewController,
|
||||||
// which stores state in this.appState and the view controller's state to this.state
|
// which stores state in this.appState and the view controller's state to this.state
|
||||||
|
@ -43,3 +43,5 @@ export class ShelvesController extends ViewController {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { ShelvesController };
|
||||||
|
|
|
@ -1,11 +1,11 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { ShelvesController } from './controller'; // The controller for this view, where processing should happen.
|
const { ShelvesController } = require('./controller'); // The controller for this view, where processing should happen.
|
||||||
import { shelfView } from './shelf';
|
const { shelfView } = require('./shelf');
|
||||||
import { userShelvesView } from './userShelves';
|
const { userShelvesView } = require('./userShelves');
|
||||||
|
|
||||||
// This is the view function that is exported and used in the view manager.
|
// This is the view function that is exported and used in the view manager.
|
||||||
export const shelvesView = (state, emit, i18n) => {
|
const shelvesView = (state, emit, i18n) => {
|
||||||
const controller = new ShelvesController(state, i18n);
|
const controller = new ShelvesController(state, i18n);
|
||||||
|
|
||||||
// Returning an array in a view allows non-shared parent HTML elements.
|
// Returning an array in a view allows non-shared parent HTML elements.
|
||||||
|
@ -17,3 +17,5 @@ export const shelvesView = (state, emit, i18n) => {
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { shelvesView };
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { starRating } from '../partials/starRating';
|
const { starRating } = require('../partials/starRating');
|
||||||
import { modal } from '../partials/modal';
|
const { modal } = require('../partials/modal');
|
||||||
|
|
||||||
export const shelfView = (shelvesController, emit) => {
|
const shelfView = (shelvesController, emit) => {
|
||||||
const { __ } = shelvesController.i18n;
|
const { __ } = shelvesController.i18n;
|
||||||
|
|
||||||
if (shelvesController.targetShelf === null) {
|
if (shelvesController.targetShelf === null) {
|
||||||
|
@ -108,3 +108,5 @@ export const shelfView = (shelvesController, emit) => {
|
||||||
</section>`,
|
</section>`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { shelfView };
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
|
|
||||||
import { modal } from '../../partials/modal';
|
const { modal } = require('../../partials/modal');
|
||||||
|
|
||||||
export const editModal = (shelf, shelvesController) => {
|
const editModal = (shelf, shelvesController) => {
|
||||||
const { __ } = shelvesController.i18n;
|
const { __ } = shelvesController.i18n;
|
||||||
|
|
||||||
const modalId = `editShelf${shelf.id}`;
|
const modalId = `editShelf${shelf.id}`;
|
||||||
|
@ -27,3 +27,5 @@ export const editModal = (shelf, shelvesController) => {
|
||||||
</footer>`,
|
</footer>`,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { editModal };
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import html from 'choo/html';
|
const html = require('choo/html');
|
||||||
import { editModal } from './editModal';
|
const { editModal } = require('./editModal');
|
||||||
|
|
||||||
export const userShelvesView = (shelvesController, emit) => {
|
const userShelvesView = (shelvesController, emit) => {
|
||||||
const { __ } = shelvesController.i18n;
|
const { __ } = shelvesController.i18n;
|
||||||
|
|
||||||
if (!shelvesController.isLoggedIn) {
|
if (!shelvesController.isLoggedIn) {
|
||||||
|
@ -20,7 +20,7 @@ export const userShelvesView = (shelvesController, emit) => {
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
if (shelvesController.state.myShelves.length <= 0) {
|
if (shelvesController.appState.isFrontend && shelvesController.state.myShelves.length <= 0) {
|
||||||
shelvesController.getUserShelves().then(() => {
|
shelvesController.getUserShelves().then(() => {
|
||||||
emit(shelvesController.appState.events.RENDER);
|
emit(shelvesController.appState.events.RENDER);
|
||||||
});
|
});
|
||||||
|
@ -53,3 +53,5 @@ export const userShelvesView = (shelvesController, emit) => {
|
||||||
</section>`,
|
</section>`,
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module.exports = { userShelvesView };
|
||||||
|
|
|
@ -36,6 +36,7 @@ async function plugin (fastify, opts, done) {
|
||||||
|
|
||||||
// Set the default language to English after parsing locales because it has the most coverage.
|
// Set the default language to English after parsing locales because it has the most coverage.
|
||||||
i18n.default = i18n.en;
|
i18n.default = i18n.en;
|
||||||
|
i18n.pages.default = i18n.pages.en;
|
||||||
} catch (ex) {
|
} catch (ex) {
|
||||||
console.error('Could not get locales folder.\n', ex);
|
console.error('Could not get locales folder.\n', ex);
|
||||||
}
|
}
|
||||||
|
@ -47,4 +48,4 @@ async function plugin (fastify, opts, done) {
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = plugin;
|
module.exports = fp(plugin);
|
|
@ -100,9 +100,7 @@ fastify.addHook('onRequest', async (request, reply) => {
|
||||||
request.user = user;
|
request.user = user;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (typeof request.cookies.lang !== 'undefined') {
|
request.language = typeof request.cookies.lang !== 'undefined' ? request.cookies.lang : 'en';
|
||||||
request.language = request.cookies.lang;
|
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|
||||||
// Store i18n files in fastify object and register locales routes
|
// Store i18n files in fastify object and register locales routes
|
||||||
|
|
|
@ -1,16 +1,30 @@
|
||||||
async function routes(fastify, options) {
|
const fs = require('fs');
|
||||||
// This route is not totally necessary because fastify-static serves public/ wholesale, but it's good to be verbose!
|
const path = require('path');
|
||||||
fastify.get('/', async (request, reply) => {
|
const htmlContainer = fs.readFileSync(path.resolve('public/index.html'));
|
||||||
return reply.sendFile('index.html');
|
const chooApp = require('../../app')();
|
||||||
});
|
const chooI18n = require('../../app/i18n').I18n;
|
||||||
|
|
||||||
|
async function routes(fastify, options) {
|
||||||
// This is overridden by any explicitly named routes, so the API will be fine.
|
// This is overridden by any explicitly named routes, so the API will be fine.
|
||||||
fastify.get('/:chooRoute', async (request, reply) => {
|
fastify.get('/:chooRoute', async (request, reply) => {
|
||||||
if (/\.\w+$/.test(request.params.chooRoute)) { // If the :chooRoute is a filename, serve the file instead
|
if (/\.\w+$/.test(request.params.chooRoute)) { // If the :chooRoute is a filename, serve the file instead
|
||||||
return reply.sendFile(request.params.chooRoute);
|
return reply.sendFile(request.params.chooRoute);
|
||||||
}
|
}
|
||||||
// Otherwise, send index.html and allow Choo to route it.
|
// Otherwise, send allow Choo to route it.
|
||||||
return reply.sendFile('index.html');
|
const state = Object.assign({}, chooApp.state);
|
||||||
|
state.language = request.language;
|
||||||
|
state.isLoggedIn = request.isLoggedInUser;
|
||||||
|
|
||||||
|
state.i18n = new chooI18n(state);
|
||||||
|
state.i18n.availableLanguages = fastify.i18n.available.slice();
|
||||||
|
state.i18n.default = Object.assign({}, fastify.i18n.default);
|
||||||
|
|
||||||
|
const locale = typeof fastify.i18n[state.language] !== 'undefined' ? state.language : 'default';
|
||||||
|
state.i18n.language = Object.assign({}, fastify.i18n[locale]);
|
||||||
|
state.i18n.pages = Object.assign({}, fastify.i18n.pages[locale]);
|
||||||
|
|
||||||
|
const html = htmlContainer.toString().replace(/\<body\>(.|\n)+?\<\/body\>/, chooApp.toString('/' + request.params.chooRoute, state));
|
||||||
|
return reply.type('text/html').send(html);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue