Compare commits
4 Commits
805ebef01c
...
aefab612e7
Author | SHA1 | Date |
---|---|---|
Robbie Antenesse | aefab612e7 | |
Robbie Antenesse | cf691f5cff | |
Robbie Antenesse | 47812f45d9 | |
Robbie Antenesse | fed8b7025b |
|
@ -3,6 +3,7 @@ import { homeView } from './views/home';
|
||||||
import { aboutView } from './views/about';
|
import { aboutView } from './views/about';
|
||||||
import { loginView } from './views/login';
|
import { loginView } from './views/login';
|
||||||
import { searchView } from './views/search';
|
import { searchView } from './views/search';
|
||||||
|
import { shelvesView } from './views/shelves';
|
||||||
import { errorView } from './views/404';
|
import { errorView } from './views/404';
|
||||||
|
|
||||||
export const appRoutes = (app) => {
|
export const appRoutes = (app) => {
|
||||||
|
@ -16,5 +17,7 @@ export const appRoutes = (app) => {
|
||||||
|
|
||||||
app.route('/search', (state, emit) => globalView(state, emit, searchView));
|
app.route('/search', (state, emit) => globalView(state, emit, searchView));
|
||||||
|
|
||||||
|
app.route('/shelves', (state, emit) => globalView(state, emit, shelvesView));
|
||||||
|
|
||||||
app.route('/404', (state, emit) => globalView(state, emit, errorView));
|
app.route('/404', (state, emit) => globalView(state, emit, errorView));
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,6 +29,10 @@ nav {
|
||||||
color: $picnic-white;
|
color: $picnic-white;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.modal {
|
||||||
|
position: absolute; // Prevent modal partial from interrupting content flow.
|
||||||
|
}
|
||||||
|
|
||||||
// External links
|
// External links
|
||||||
a[href^="http://"]:after,
|
a[href^="http://"]:after,
|
||||||
a[href^="https://"]:after{
|
a[href^="https://"]:after{
|
||||||
|
|
|
@ -29,6 +29,7 @@ export const globalView = (state, emit, view) => {
|
||||||
${
|
${
|
||||||
state.isLoggedIn === true
|
state.isLoggedIn === true
|
||||||
? [
|
? [
|
||||||
|
html`<a href="/shelves" class="pseudo button">${i18n.__('global.menu_shelves')}</a>`,
|
||||||
html`<a href="/account" class="pseudo button">${i18n.__('global.menu_account')}</a>`,
|
html`<a href="/account" class="pseudo button">${i18n.__('global.menu_account')}</a>`,
|
||||||
html`<a href="/logout" class="pseudo button">${i18n.__('global.menu_logout')}</a>`,
|
html`<a href="/logout" class="pseudo button">${i18n.__('global.menu_logout')}</a>`,
|
||||||
]
|
]
|
||||||
|
|
|
@ -27,11 +27,8 @@ export class ShelvesController extends ViewController {
|
||||||
}
|
}
|
||||||
|
|
||||||
getUserShelves () {
|
getUserShelves () {
|
||||||
return [
|
return fetch('/api/shelves/get').then(response => response.json()).then(shelves => {
|
||||||
{id:1,name:'Test Shelf',isDeletable:false,isPublilc:false},
|
this.state.myShelves = shelves;
|
||||||
{id:1,name:'Deletable Shelf',isDeletable:true,isPublilc:false},
|
});
|
||||||
{id:1,name:'Public Shelf',isDeletable:true,isPublilc:true},
|
|
||||||
];
|
|
||||||
// return fetch('/api/shelves/get').then(response => response.json);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -2,7 +2,7 @@ import html from 'choo/html';
|
||||||
|
|
||||||
import { ShelvesController } from './controller'; // The controller for this view, where processing should happen.
|
import { ShelvesController } from './controller'; // The controller for this view, where processing should happen.
|
||||||
import { shelfView } from './shelf';
|
import { shelfView } from './shelf';
|
||||||
import { shelvesView } from './shelves';
|
import { userShelvesView } from './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) => {
|
export const shelvesView = (state, emit, i18n) => {
|
||||||
|
@ -13,7 +13,7 @@ export const shelvesView = (state, emit, i18n) => {
|
||||||
return [
|
return [
|
||||||
(controller.targetShelf !== null
|
(controller.targetShelf !== null
|
||||||
? shelfView(controller, emit)
|
? shelfView(controller, emit)
|
||||||
: shelvesView(controller, emit)
|
: userShelvesView(controller, emit)
|
||||||
),
|
),
|
||||||
];
|
];
|
||||||
}
|
}
|
|
@ -1,12 +0,0 @@
|
||||||
import html from 'choo/html';
|
|
||||||
|
|
||||||
export const editModal = (shelf, shelvesController) => {
|
|
||||||
const { __ } = shelvesController.i18n;
|
|
||||||
|
|
||||||
// Should add a scale of publicity: private, friends only, friends & followers, public
|
|
||||||
return [
|
|
||||||
html`<article>
|
|
||||||
<p>To Do</p>
|
|
||||||
</article>`,
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -1,66 +0,0 @@
|
||||||
import html from 'choo/html';
|
|
||||||
import modal from '../partials/modal';
|
|
||||||
|
|
||||||
export const shelvesView = (shelvesController, emit) => {
|
|
||||||
const { __ } = shelvesController.i18n;
|
|
||||||
|
|
||||||
if (!shelvesController.isLoggedIn) {
|
|
||||||
return [
|
|
||||||
html`<section>
|
|
||||||
<h2>${__('shelves.no_shelf_selected')}</h2>
|
|
||||||
<article class="card">
|
|
||||||
<header>
|
|
||||||
<p>${__('shelves.not_logged_in')}</p>
|
|
||||||
</header>
|
|
||||||
<footer>
|
|
||||||
<button>${__('global.menu_login')}</button>
|
|
||||||
</footer>
|
|
||||||
</article>
|
|
||||||
</section>`,
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
if (shelvesController.state.myShelves.length <= 0) {
|
|
||||||
shelvesController.getUserShelves().then(result => {
|
|
||||||
emit('render');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
// Should add a scale of publicity: private, friends only, friends & followers, public
|
|
||||||
return [
|
|
||||||
html`<section>
|
|
||||||
<h2>${__('shelves.title')}</h2>
|
|
||||||
${controller.state.myShelves.map(shelf => {
|
|
||||||
return html`<article class="card">
|
|
||||||
<header>
|
|
||||||
<h3>
|
|
||||||
<a href="/shelves?shelf=${shelf.id}">${shelf.name}</a>
|
|
||||||
</h3>
|
|
||||||
${shelf.isDeletable === true
|
|
||||||
? [
|
|
||||||
modal(`editShelf${shelf.id}`, shelvesController, editModal(shelf, shelvesController), {
|
|
||||||
buttonHTML: html`<button class="small pseudo pull-right tooltip-left" data-tooltip=${__('interaction.edit')}>
|
|
||||||
<i class="icon-edit"></i>
|
|
||||||
</button>`,
|
|
||||||
headerText: `${__('shelves.edit.editing')}: ${shelf.name}`,
|
|
||||||
footerHTML: html`<footer>
|
|
||||||
<button>
|
|
||||||
${__('shelves.edit.save')}
|
|
||||||
</button>
|
|
||||||
<label for=${modalId} class="button dangerous">
|
|
||||||
${__('interaction.close')}
|
|
||||||
</label>
|
|
||||||
</footer>`,
|
|
||||||
}),
|
|
||||||
|
|
||||||
html`<button class="small pseudo pull-right tooltip-left" data-tooltip=${__('interaction.delete')}>
|
|
||||||
<i class="icon-delete"></i>
|
|
||||||
</button>`,
|
|
||||||
]
|
|
||||||
: null}
|
|
||||||
</header>
|
|
||||||
</article>`;
|
|
||||||
})}
|
|
||||||
</section>`,
|
|
||||||
];
|
|
||||||
}
|
|
|
@ -0,0 +1,29 @@
|
||||||
|
import html from 'choo/html';
|
||||||
|
|
||||||
|
import { modal } from '../../partials/modal';
|
||||||
|
|
||||||
|
export const editModal = (shelf, shelvesController) => {
|
||||||
|
const { __ } = shelvesController.i18n;
|
||||||
|
|
||||||
|
const modalId = `editShelf${shelf.id}`;
|
||||||
|
|
||||||
|
// Should add a scale of publicity: private, friends only, friends & followers, public
|
||||||
|
const modalContent = html`<article>
|
||||||
|
<p>To Do</p>
|
||||||
|
</article>`;
|
||||||
|
|
||||||
|
return modal(modalId, shelvesController, modalContent, {
|
||||||
|
buttonHTML: html`<label for=${modalId} class="small pseudo button">
|
||||||
|
${__('interaction.edit')} <i class="icon-edit"></i>
|
||||||
|
</label>`,
|
||||||
|
headerText: `${__('shelves.edit.editing')}: ${shelf.name}`,
|
||||||
|
footerHTML: html`<footer>
|
||||||
|
<button>
|
||||||
|
${__('shelves.edit.save')}
|
||||||
|
</button>
|
||||||
|
<label for=${modalId} class="button dangerous">
|
||||||
|
${__('interaction.close')}
|
||||||
|
</label>
|
||||||
|
</footer>`,
|
||||||
|
});
|
||||||
|
}
|
|
@ -0,0 +1,55 @@
|
||||||
|
import html from 'choo/html';
|
||||||
|
import { editModal } from './editModal';
|
||||||
|
|
||||||
|
export const userShelvesView = (shelvesController, emit) => {
|
||||||
|
const { __ } = shelvesController.i18n;
|
||||||
|
|
||||||
|
if (!shelvesController.isLoggedIn) {
|
||||||
|
return [
|
||||||
|
html`<section>
|
||||||
|
<h2>${__('shelves.no_shelf_selected')}</h2>
|
||||||
|
<article class="card">
|
||||||
|
<header>
|
||||||
|
<p>${__('shelves.not_logged_in')}</p>
|
||||||
|
</header>
|
||||||
|
<footer>
|
||||||
|
<button>${__('global.menu_login')}</button>
|
||||||
|
</footer>
|
||||||
|
</article>
|
||||||
|
</section>`,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
if (shelvesController.state.myShelves.length <= 0) {
|
||||||
|
shelvesController.getUserShelves().then(() => {
|
||||||
|
emit('render');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
// Should add a scale of publicity: private, friends only, friends & followers, public
|
||||||
|
return [
|
||||||
|
html`<section>
|
||||||
|
<h2>${__('shelves.title')}</h2>
|
||||||
|
${shelvesController.state.myShelves.map(shelf => {
|
||||||
|
const deleteButton = html`<button class="small pseudo">
|
||||||
|
${__('interaction.delete')} <i class="icon-delete"></i>
|
||||||
|
</button>`;
|
||||||
|
|
||||||
|
return html`<article class="card">
|
||||||
|
<header>
|
||||||
|
<h3>
|
||||||
|
<a href="/shelves?shelf=${shelf.id}">${shelf.name}</a>
|
||||||
|
</h3>
|
||||||
|
${shelf.isDeletable === true
|
||||||
|
? [
|
||||||
|
editModal(shelf, shelvesController),
|
||||||
|
[deleteButton], // editModal outputs a modal, which returns an array, so any subsequent html items must also be in an array for Choo to handle it correctly.
|
||||||
|
]
|
||||||
|
: null
|
||||||
|
}
|
||||||
|
</header>
|
||||||
|
</article>`;
|
||||||
|
})}
|
||||||
|
</section>`,
|
||||||
|
];
|
||||||
|
}
|
|
@ -93,20 +93,18 @@ class ShelfController {
|
||||||
}
|
}
|
||||||
|
|
||||||
async getLastUpdatedTimestamp (shelf) {
|
async getLastUpdatedTimestamp (shelf) {
|
||||||
const lastEditedItem = await this.itemModel.findOne({
|
const lastEditedItem = await shelf.getShelfItems({
|
||||||
attributes: ['updatedAt'],
|
attributes: ['updatedAt'],
|
||||||
where: {
|
|
||||||
shelf: shelf.id,
|
|
||||||
},
|
|
||||||
order: [
|
order: [
|
||||||
[
|
[
|
||||||
'updatedAt',
|
'updatedAt',
|
||||||
'DESC'
|
'DESC'
|
||||||
],
|
],
|
||||||
],
|
],
|
||||||
|
limit: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
if (lastEditedItem && lastEditedItem.updatedAt > shelf.updatedAt) {
|
if (lastEditedItem.length > 0 && (lastEditedItem[0].updatedAt > shelf.updatedAt)) {
|
||||||
return lastEditedItem.updatedAt;
|
return lastEditedItem.updatedAt;
|
||||||
}
|
}
|
||||||
return shelf.updatedAt;
|
return shelf.updatedAt;
|
||||||
|
|
|
@ -7,7 +7,7 @@ async function routes(fastify, options) {
|
||||||
return false;
|
return false;
|
||||||
});
|
});
|
||||||
|
|
||||||
fastify.post('/api/shelves/get', async (request, reply) => {
|
fastify.get('/api/shelves/get', async (request, reply) => {
|
||||||
if (!request.isLoggedInUser) {
|
if (!request.isLoggedInUser) {
|
||||||
return reply.code(400).send({
|
return reply.code(400).send({
|
||||||
error: true,
|
error: true,
|
||||||
|
@ -15,8 +15,15 @@ async function routes(fastify, options) {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
return request.user.getShelves({
|
const shelfController = new ShelfController(fastify.models.Shelf, fastify.models.ShelfItem);
|
||||||
attributes: ['id', 'name', 'isDeletable', 'isPublic'],
|
|
||||||
|
const shelves = await request.user.getShelves({
|
||||||
|
attributes: ['id', 'name', 'isDeletable', 'isPublic', 'updatedAt'],
|
||||||
|
});
|
||||||
|
|
||||||
|
return shelves.map(shelf => {
|
||||||
|
shelf.updatedAt = shelfController.getLastUpdatedTimestamp(shelf);
|
||||||
|
return shelf;
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue