Skip to content

Commit

Permalink
feat: Added detail screen
Browse files Browse the repository at this point in the history
* feat: added detail screen

Co-authored-by: MauritsioRK <maurits_rk@hotmail.com>
Co-authored-by: Martijn Vegter <martijn@martijnvegter.com>
  • Loading branch information
3 people committed Apr 24, 2020
1 parent f618ccc commit e0bc9e3
Show file tree
Hide file tree
Showing 11 changed files with 204 additions and 54 deletions.
3 changes: 2 additions & 1 deletion .eslintrc
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
"node": true
},
"parserOptions": {
"ecmaVersion": 8,
"ecmaVersion": 2018,
"sourceType": "module"
},
"extends": [
Expand Down Expand Up @@ -58,6 +58,7 @@
],
"init-declarations": "off",
"key-spacing": "error",
"keyword-spacing": "error",
"linebreak-style": "off",
"lines-around-comment": [
"error",
Expand Down
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -109,3 +109,6 @@ tmp/
temp/

# End of https://www.gitignore.io/api/node

# Ignore .vscode folder
.vscode
34 changes: 32 additions & 2 deletions lib/framework/persistence/repositories/InMemoryLogRepository.js
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,40 @@ class InMemoryLogRepository extends LogRepository {
/**
* Returns all entities.
*
* @returns {Promise} Promise object represents the ...
* @returns {Promise} Promise object representing the full mock data
*/
async findAll() {
return Promise.resolve([]);
const date = new Date().getTime();
return Promise.resolve([
{
entryID: 1,
authorID: 'Batman',
title: 'Run1',
creationTime: date,
tags: ['Tag1', 'Tag2'],
content: [
{ content: 'Batman wrote this...', sender: 'Batman' },
{ content: 'Nightwing wrote this...', sender: 'Nightwing' },
{ content: 'Gordon wrote this...', sender: 'Commissioner Gordon' },
],
},
{
entryID: 2,
authorID: 'Joker',
title: 'Run2',
creationTime: date,
tags: ['Tag2'],
content: [{ content: 'Something about run2...', sender: 'Joker' }],
},
{
entryID: 3,
authorID: 'Anonymous',
title: 'Run5',
creationTime: date,
tags: ['Tag3'],
content: [{ content: 'Ipem lorum...', sender: 'Anonymous' }],
},
]);
}
}

Expand Down
2 changes: 2 additions & 0 deletions lib/public/Model.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,8 @@ export default class Model extends Observable {
switch (this.router.params.page) {
case 'home':
break;
case 'entry':
break;
default:
this.router.go('?page=home');
break;
Expand Down
35 changes: 35 additions & 0 deletions lib/public/components/Post/index.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
/**
* This file is part of the ALICE Electronic Logbook v2, also known as Jiskefet.
* Copyright (C) 2020 Stichting Hogeschool van Amsterdam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { h } from '/js/src/index.js';

/**
* A singular post which is part of a log
* @param {Object} post all data related to the post
* @param {Number} index the identification index of the post
* @return {vnode} Returns the navbar
*/
const entry = (post, index) =>
h('.flex-column.p2.shadow-level1.mv2', {
id: `post${index}`,
}, [
h('.f7.gray-darker', { style: 'align-self: flex-end;' }, `#${index}`),
h('.w-100.bg-gray-light.mv1.ph1', post.content),
h('.w-75.mv1.ph1', `Written by: ${post.sender}`),
]);

export default entry;
11 changes: 6 additions & 5 deletions lib/public/components/Table/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -35,14 +35,15 @@ const rowData = (data) => [h('td', data)];
* Renders the table
* @param {Array} data The data array containing the objects with the data per row
* @param {Array} headers The array of of the headers to be rendered in the table
* @param {Object} model Model passed for use with routing to the correct detail view
* @returns {vnode} Return the total view of the table to rendered
*/
const table = (data, headers) => h('table.table.shadow-level1.mh3', [
const table = (data, headers, model) => h('table.table.shadow-level1.mh3', [
h('tr', [headers.map((header) => rowHeader(header))]),
data.map((entry, index) => h('tr', [
rowData(index + 1),
Object.keys(entry).map((subItem) => rowData(entry[subItem])),
])),
data.map((entry, index) => h(`tr#row${index + 1}`, {
onclick: () => model.router.go(`?page=entry&id=${entry[0]}`),

}, [Object.keys(entry).map((subItem) => rowData(entry[subItem]) )])),
]);

export { table };
14 changes: 10 additions & 4 deletions lib/public/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,21 +19,26 @@
import { h, switchCase } from '/js/src/index.js';
import NavBar from './components/NavBar/index.js';
import GeneralOverview from './views/Overview/General/page.js';
import DetailsView from './views/Overview/Details/page.js';

/**
* Main view layout
* @param {object} model - representing current application state
* @return {vnode} application view to be drawn according to model
*/
export default (model) => {
const pages = {
const navigationPages = {
home: GeneralOverview,
};

const subPages = {
entry: DetailsView,
};

return [
h('.flex-column.absolute-fill', [
NavBar(model, pages),
content(model, pages),
NavBar(model, navigationPages),
content(model, { ...navigationPages, ...subPages }),
]),
];
};
Expand All @@ -44,4 +49,5 @@ export default (model) => {
* @param {Object} pages Pass the pages to the switchcase
* @returns {vnode} Returns a vnode to render the pages
*/
const content = (model, pages) => h('.p4', switchCase(model.router.params.page, pages)(model));
const content = (model, pages) =>
h('.p4', switchCase(model.router.params.page, pages)(model));
40 changes: 40 additions & 0 deletions lib/public/views/Overview/Details/page.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
/**
* This file is part of the ALICE Electronic Logbook v2, also known as Jiskefet.
* Copyright (C) 2020 Stichting Hogeschool van Amsterdam
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU Affero General Public License as published
* by the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Affero General Public License for more details.
*
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { h } from '/js/src/index.js';
import PostBox from '../../../components/Post/index.js';

/**
* A collection of details relating to a log
* @param {object} model Pass the model to access the defined functions
* @return {vnode} Return the view of the table with the filtering options
*/
const overviewScreen = (model) => {
const data = model.overview.getData();
const id = parseInt(model.router.params.id);
let posts;

data.forEach((entry) => {
if (entry.entryID === id) {
posts = entry.content;
}
});

return h('.w-100.flex-column', [posts.map((post, index) => h('.w-100', PostBox(post, index + 1)))]);
};

export default (model) => [overviewScreen(model)];
8 changes: 4 additions & 4 deletions lib/public/views/Overview/General/page.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,20 +19,20 @@ import { h } from '/js/src/index.js';
import filters from '../../../components/Filters/index.js';
import { table } from '../../../components/Table/index.js';

export default (model) => [overviewScreen(model)];

/**
* Table row header
* @param {object} model Pass the model to access the defined functions
* @return {vnode} Return the view of the table with the filtering options
*/
const overviewScreen = (model) => {
const headers = model.overview.getHeaders();
const data = model.overview.getTableData();
const data = model.overview.getDataWithoutTags();
const tags = model.overview.getTagCounts();

return h('.w-100.flex-row', [
filters(model, tags),
h('.w-75', [table(data, headers)]),
h('.w-75', [table(data, headers, model)]),
]);
};

export default (model) => [overviewScreen(model)];
62 changes: 34 additions & 28 deletions lib/public/views/Overview/Overview.js
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@
* You should have received a copy of the GNU Affero General Public License
* along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
import { Observable } from '/js/src/index.js';
import { Observable, fetchClient } from '/js/src/index.js';

/**
* Model representing handlers for homePage.js
Expand All @@ -29,30 +29,12 @@ export default class Overview extends Observable {
constructor(model) {
super();
this.model = model;
this.date = new Date().toDateString();
this.filterCriteria = [];
this.data = [
{
authorID: 'Batman',
title: 'Run1',
creationTime: this.date,
tags: ['Tag1', 'Tag2'],
},
{
authorID: 'Joker',
title: 'Run2',
creationTime: this.date,
tags: ['Tag2'],
},
{
authorID: 'Anonymous',
title: 'Run5',
creationTime: this.date,
tags: ['Tag3'],
},
];
this.filtered = [...this.data];
this.data = [];
this.filtered = [];
this.headers = ['ID', 'Author ID', 'Title', 'Creation Time'];

this.fetchData();
}

/**
Expand All @@ -63,19 +45,43 @@ export default class Overview extends Observable {
return this.headers;
}

/**
* Fetch all relevant logs data from api
* @returns {undefined} Injects the data object with the response data
*/
async fetchData() {
const response = await fetchClient('/api/logs', { method: 'GET' });
const result = await response.json();
this.data = result.data;
this.filtered = [...result.data];
this.notify();
}

/**
* Getter for all the data
* @returns {Array} Returns all of the data
*/
getData() {
return this.data;
}

/**
* Get the table data
* @returns {Array} The data without the tags to be rendered in a table
*/
getTableData() {
getDataWithoutTags() {
const subentries = this.filtered.map((entry) => {
const filter = Object.keys(entry).map((subkey) => {
if (subkey !== 'tags') {
const columnData = Object.keys(entry).map((subkey) => {
// Filter out the field not needed for the table
if (subkey !== 'tags' && subkey !== 'content') {
if (subkey === 'creationTime') {
return new Date(entry[subkey]).toLocaleString();
}

return entry[subkey];
}
});

return filter;
return columnData.filter((item) => item !== undefined);
});

return subentries;
Expand Down
Loading

0 comments on commit e0bc9e3

Please sign in to comment.