Skip to content

Commit e0bc9e3

Browse files
john-ghatasMauritsioRKmvegter
committed
feat: Added detail screen
* feat: added detail screen Co-authored-by: MauritsioRK <maurits_rk@hotmail.com> Co-authored-by: Martijn Vegter <martijn@martijnvegter.com>
1 parent f618ccc commit e0bc9e3

11 files changed

Lines changed: 204 additions & 54 deletions

File tree

.eslintrc

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
"node": true
66
},
77
"parserOptions": {
8-
"ecmaVersion": 8,
8+
"ecmaVersion": 2018,
99
"sourceType": "module"
1010
},
1111
"extends": [
@@ -58,6 +58,7 @@
5858
],
5959
"init-declarations": "off",
6060
"key-spacing": "error",
61+
"keyword-spacing": "error",
6162
"linebreak-style": "off",
6263
"lines-around-comment": [
6364
"error",

.gitignore

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,3 +109,6 @@ tmp/
109109
temp/
110110

111111
# End of https://www.gitignore.io/api/node
112+
113+
# Ignore .vscode folder
114+
.vscode

lib/framework/persistence/repositories/InMemoryLogRepository.js

Lines changed: 32 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,40 @@ class InMemoryLogRepository extends LogRepository {
2525
/**
2626
* Returns all entities.
2727
*
28-
* @returns {Promise} Promise object represents the ...
28+
* @returns {Promise} Promise object representing the full mock data
2929
*/
3030
async findAll() {
31-
return Promise.resolve([]);
31+
const date = new Date().getTime();
32+
return Promise.resolve([
33+
{
34+
entryID: 1,
35+
authorID: 'Batman',
36+
title: 'Run1',
37+
creationTime: date,
38+
tags: ['Tag1', 'Tag2'],
39+
content: [
40+
{ content: 'Batman wrote this...', sender: 'Batman' },
41+
{ content: 'Nightwing wrote this...', sender: 'Nightwing' },
42+
{ content: 'Gordon wrote this...', sender: 'Commissioner Gordon' },
43+
],
44+
},
45+
{
46+
entryID: 2,
47+
authorID: 'Joker',
48+
title: 'Run2',
49+
creationTime: date,
50+
tags: ['Tag2'],
51+
content: [{ content: 'Something about run2...', sender: 'Joker' }],
52+
},
53+
{
54+
entryID: 3,
55+
authorID: 'Anonymous',
56+
title: 'Run5',
57+
creationTime: date,
58+
tags: ['Tag3'],
59+
content: [{ content: 'Ipem lorum...', sender: 'Anonymous' }],
60+
},
61+
]);
3262
}
3363
}
3464

lib/public/Model.js

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -61,6 +61,8 @@ export default class Model extends Observable {
6161
switch (this.router.params.page) {
6262
case 'home':
6363
break;
64+
case 'entry':
65+
break;
6466
default:
6567
this.router.go('?page=home');
6668
break;
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
/**
2+
* This file is part of the ALICE Electronic Logbook v2, also known as Jiskefet.
3+
* Copyright (C) 2020 Stichting Hogeschool van Amsterdam
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published
7+
* by the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
import { h } from '/js/src/index.js';
19+
20+
/**
21+
* A singular post which is part of a log
22+
* @param {Object} post all data related to the post
23+
* @param {Number} index the identification index of the post
24+
* @return {vnode} Returns the navbar
25+
*/
26+
const entry = (post, index) =>
27+
h('.flex-column.p2.shadow-level1.mv2', {
28+
id: `post${index}`,
29+
}, [
30+
h('.f7.gray-darker', { style: 'align-self: flex-end;' }, `#${index}`),
31+
h('.w-100.bg-gray-light.mv1.ph1', post.content),
32+
h('.w-75.mv1.ph1', `Written by: ${post.sender}`),
33+
]);
34+
35+
export default entry;

lib/public/components/Table/index.js

Lines changed: 6 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -35,14 +35,15 @@ const rowData = (data) => [h('td', data)];
3535
* Renders the table
3636
* @param {Array} data The data array containing the objects with the data per row
3737
* @param {Array} headers The array of of the headers to be rendered in the table
38+
* @param {Object} model Model passed for use with routing to the correct detail view
3839
* @returns {vnode} Return the total view of the table to rendered
3940
*/
40-
const table = (data, headers) => h('table.table.shadow-level1.mh3', [
41+
const table = (data, headers, model) => h('table.table.shadow-level1.mh3', [
4142
h('tr', [headers.map((header) => rowHeader(header))]),
42-
data.map((entry, index) => h('tr', [
43-
rowData(index + 1),
44-
Object.keys(entry).map((subItem) => rowData(entry[subItem])),
45-
])),
43+
data.map((entry, index) => h(`tr#row${index + 1}`, {
44+
onclick: () => model.router.go(`?page=entry&id=${entry[0]}`),
45+
46+
}, [Object.keys(entry).map((subItem) => rowData(entry[subItem]) )])),
4647
]);
4748

4849
export { table };

lib/public/view.js

Lines changed: 10 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,26 @@
1919
import { h, switchCase } from '/js/src/index.js';
2020
import NavBar from './components/NavBar/index.js';
2121
import GeneralOverview from './views/Overview/General/page.js';
22+
import DetailsView from './views/Overview/Details/page.js';
2223

2324
/**
2425
* Main view layout
2526
* @param {object} model - representing current application state
2627
* @return {vnode} application view to be drawn according to model
2728
*/
2829
export default (model) => {
29-
const pages = {
30+
const navigationPages = {
3031
home: GeneralOverview,
3132
};
3233

34+
const subPages = {
35+
entry: DetailsView,
36+
};
37+
3338
return [
3439
h('.flex-column.absolute-fill', [
35-
NavBar(model, pages),
36-
content(model, pages),
40+
NavBar(model, navigationPages),
41+
content(model, { ...navigationPages, ...subPages }),
3742
]),
3843
];
3944
};
@@ -44,4 +49,5 @@ export default (model) => {
4449
* @param {Object} pages Pass the pages to the switchcase
4550
* @returns {vnode} Returns a vnode to render the pages
4651
*/
47-
const content = (model, pages) => h('.p4', switchCase(model.router.params.page, pages)(model));
52+
const content = (model, pages) =>
53+
h('.p4', switchCase(model.router.params.page, pages)(model));
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
/**
2+
* This file is part of the ALICE Electronic Logbook v2, also known as Jiskefet.
3+
* Copyright (C) 2020 Stichting Hogeschool van Amsterdam
4+
*
5+
* This program is free software: you can redistribute it and/or modify
6+
* it under the terms of the GNU Affero General Public License as published
7+
* by the Free Software Foundation, either version 3 of the License, or
8+
* (at your option) any later version.
9+
*
10+
* This program is distributed in the hope that it will be useful,
11+
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12+
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13+
* GNU Affero General Public License for more details.
14+
*
15+
* You should have received a copy of the GNU Affero General Public License
16+
* along with this program. If not, see <https://www.gnu.org/licenses/>.
17+
*/
18+
import { h } from '/js/src/index.js';
19+
import PostBox from '../../../components/Post/index.js';
20+
21+
/**
22+
* A collection of details relating to a log
23+
* @param {object} model Pass the model to access the defined functions
24+
* @return {vnode} Return the view of the table with the filtering options
25+
*/
26+
const overviewScreen = (model) => {
27+
const data = model.overview.getData();
28+
const id = parseInt(model.router.params.id);
29+
let posts;
30+
31+
data.forEach((entry) => {
32+
if (entry.entryID === id) {
33+
posts = entry.content;
34+
}
35+
});
36+
37+
return h('.w-100.flex-column', [posts.map((post, index) => h('.w-100', PostBox(post, index + 1)))]);
38+
};
39+
40+
export default (model) => [overviewScreen(model)];

lib/public/views/Overview/General/page.js

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -19,20 +19,20 @@ import { h } from '/js/src/index.js';
1919
import filters from '../../../components/Filters/index.js';
2020
import { table } from '../../../components/Table/index.js';
2121

22-
export default (model) => [overviewScreen(model)];
23-
2422
/**
2523
* Table row header
2624
* @param {object} model Pass the model to access the defined functions
2725
* @return {vnode} Return the view of the table with the filtering options
2826
*/
2927
const overviewScreen = (model) => {
3028
const headers = model.overview.getHeaders();
31-
const data = model.overview.getTableData();
29+
const data = model.overview.getDataWithoutTags();
3230
const tags = model.overview.getTagCounts();
3331

3432
return h('.w-100.flex-row', [
3533
filters(model, tags),
36-
h('.w-75', [table(data, headers)]),
34+
h('.w-75', [table(data, headers, model)]),
3735
]);
3836
};
37+
38+
export default (model) => [overviewScreen(model)];

lib/public/views/Overview/Overview.js

Lines changed: 34 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
* You should have received a copy of the GNU Affero General Public License
1616
* along with this program. If not, see <https://www.gnu.org/licenses/>.
1717
*/
18-
import { Observable } from '/js/src/index.js';
18+
import { Observable, fetchClient } from '/js/src/index.js';
1919

2020
/**
2121
* Model representing handlers for homePage.js
@@ -29,30 +29,12 @@ export default class Overview extends Observable {
2929
constructor(model) {
3030
super();
3131
this.model = model;
32-
this.date = new Date().toDateString();
3332
this.filterCriteria = [];
34-
this.data = [
35-
{
36-
authorID: 'Batman',
37-
title: 'Run1',
38-
creationTime: this.date,
39-
tags: ['Tag1', 'Tag2'],
40-
},
41-
{
42-
authorID: 'Joker',
43-
title: 'Run2',
44-
creationTime: this.date,
45-
tags: ['Tag2'],
46-
},
47-
{
48-
authorID: 'Anonymous',
49-
title: 'Run5',
50-
creationTime: this.date,
51-
tags: ['Tag3'],
52-
},
53-
];
54-
this.filtered = [...this.data];
33+
this.data = [];
34+
this.filtered = [];
5535
this.headers = ['ID', 'Author ID', 'Title', 'Creation Time'];
36+
37+
this.fetchData();
5638
}
5739

5840
/**
@@ -63,19 +45,43 @@ export default class Overview extends Observable {
6345
return this.headers;
6446
}
6547

48+
/**
49+
* Fetch all relevant logs data from api
50+
* @returns {undefined} Injects the data object with the response data
51+
*/
52+
async fetchData() {
53+
const response = await fetchClient('/api/logs', { method: 'GET' });
54+
const result = await response.json();
55+
this.data = result.data;
56+
this.filtered = [...result.data];
57+
this.notify();
58+
}
59+
60+
/**
61+
* Getter for all the data
62+
* @returns {Array} Returns all of the data
63+
*/
64+
getData() {
65+
return this.data;
66+
}
67+
6668
/**
6769
* Get the table data
6870
* @returns {Array} The data without the tags to be rendered in a table
6971
*/
70-
getTableData() {
72+
getDataWithoutTags() {
7173
const subentries = this.filtered.map((entry) => {
72-
const filter = Object.keys(entry).map((subkey) => {
73-
if (subkey !== 'tags') {
74+
const columnData = Object.keys(entry).map((subkey) => {
75+
// Filter out the field not needed for the table
76+
if (subkey !== 'tags' && subkey !== 'content') {
77+
if (subkey === 'creationTime') {
78+
return new Date(entry[subkey]).toLocaleString();
79+
}
80+
7481
return entry[subkey];
7582
}
7683
});
77-
78-
return filter;
84+
return columnData.filter((item) => item !== undefined);
7985
});
8086

8187
return subentries;

0 commit comments

Comments
 (0)