Commit b6eaf916 authored by Alexander Dietmüller's avatar Alexander Dietmüller

Frontend: Add .css for layout and example polythene component.

parent bfa9c001
<html>
<head>
<title>PVK Tool</title>
<style>
main {
display: inline-block;
vertical-align: top;
width: 60%;
}
aside {
display: inline-block;
vertical-align: top;
width: 35%;
margin-right: 5%;
}
</style>
<title>PVK Tool</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<title>AMIV Bouncer</title>
</head>
<body>
<script src="dist/bundle.js"></script>
<script src="dist/bundle.js"></script>
</body>
</html>
......@@ -13,23 +13,26 @@
},
"author": "AMIV IT team",
"dependencies": {
"dev": "^0.1.3",
"local-storage": "^1.4.2",
"mithril": "^1.1.5"
"mithril": "^1.1.5",
"polythene-css": "^1.0.0",
"polythene-mithril": "^1.0.0"
},
"devDependencies": {
"eslint": "^4.10.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0",
"webpack-dev-server": "^2.9.3",
"babel-core": "^6.26.0",
"babel-cli": "^6.26.0",
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.1",
"compression-webpack-plugin": "^1.0.1",
"file-loader": "^1.1.5",
"css-loader": "^0.28.7",
"eslint": "^4.10.0",
"eslint-config-airbnb-base": "^12.1.0",
"eslint-plugin-import": "^2.8.0",
"file-loader": "^1.1.5",
"style-loader": "^0.19.0",
"uglifyjs-webpack-plugin": "^1.0.1",
"webpack": "^3.8.1"
"webpack": "^3.8.1",
"webpack-dev-server": "^2.9.5"
}
}
......@@ -6,6 +6,8 @@
import m from 'mithril';
import session from './session';
import './layout.css';
let nethz = '';
let password = '';
let error = '';
......@@ -80,15 +82,15 @@ class LoginPage {
class SidebarHeader {
static view() {
return [
m('h1', 'PVK Tool Demo'),
m('p', `Hello, ${session.user.name}`),
m('button', { onclick: logout }, 'Logout'),
session.admin ? [
m('br'),
m('h1.header-logo', 'PVK Tool Demo'),
session.admin ? m('.header-admin-switch', [
m('a', { href: '/course', oncreate: m.route.link }, 'User Tools'),
m('br'),
m('a', { href: '/admin', oncreate: m.route.link }, 'Admin Tools'),
] : [],
]) : [],
m('.header-logout', [
m('p', `Hello, ${session.user.name}`),
m('button', { onclick: logout }, 'Logout'),
]),
];
}
}
......@@ -96,9 +98,10 @@ class SidebarHeader {
export default class Layout {
static view(vnode) {
return session.active() ? m('', [
m('aside', [m(SidebarHeader), m(vnode.attrs.sidebar)]),
return session.active() ? [
m('header', m(SidebarHeader)),
m('aside', m(vnode.attrs.sidebar)),
m('main', m(vnode.attrs.content)),
]) : m(LoginPage);
] : m(LoginPage);
}
}
// User Sidebar
import m from 'mithril';
import { userCourses, courses } from './backend';
import SidebarCard from './components/SidebarCard';
class CourseView {
static view({ attrs: { _id, courseId, remove } }) {
......@@ -22,35 +24,46 @@ export default class UserSidebar {
static view() {
return [
m('h1', 'Selected Courses'),
userCourses.selected.length ? [
userCourses.selected.map(({ _id, course: courseId }) =>
m(
CourseView,
{ _id, courseId, remove() { userCourses.deselect(_id); } },
)),
m('button', { onclick() { userCourses.reserve(); } }, 'reserve'),
] : m('p', 'No courses selected.'),
m(SidebarCard, {
title: 'Selected Courses',
content: userCourses.selected.length ? [
userCourses.selected.map(({ _id, course: courseId }) =>
m(
CourseView,
{ _id, courseId, remove() { userCourses.deselect(_id); } },
)),
] : 'No courses selected.',
action() { userCourses.reserve(); },
actionName: 'reserve',
}),
m('h1', 'Reserved Courses'),
userCourses.reserved.length ? [
userCourses.reserved.map(({ _id, course: courseId }) =>
m(SidebarCard, {
title: 'Waiting List',
content: userCourses.waiting.map(({ _id, course: courseId }) =>
m(
CourseView,
{ _id, courseId, remove() { userCourses.free(_id); } },
)),
// m('button', { onclick() { userCourses.pay(); } }, 'Pay'),
] : m('p', 'No courses reserved.'),
userCourses.waiting.length ? [
m('h4', 'Waiting'),
userCourses.waiting.map(({ _id, course: courseId }) =>
m(
CourseView,
{ _id, courseId, remove() { userCourses.free(_id); } },
)),
] : [],
m('h1', 'Accepted Courses'),
m('p', 'No courses accepted.'), // TODO: Implement
}),
m(SidebarCard, {
title: 'Reserved Courses',
content: userCourses.reserved.length ? [
userCourses.reserved.map(({ _id, course: courseId }) =>
m(
CourseView,
{ _id, courseId, remove() { userCourses.free(_id); } },
)),
] : 'No courses reserved.',
action() { userCourses.pay(); },
actionName: 'pay',
}),
m(SidebarCard, {
title: 'Accepted Courses',
content: 'No courses accepted.',
}),
];
}
}
import m from 'mithril';
import { Card, Button } from 'polythene-mithril';
import { addTypography, addLayoutStyles } from 'polythene-css';
addTypography();
addLayoutStyles(); // to use m('.flex')
export default class SidebarCard {
static view({
attrs: {
title,
subtitle = '',
content,
actionName = undefined,
actionActive = true,
action = undefined,
},
}) {
return m(Card, {
content: [
{
header: { title, subtitle },
},
{
text: { content },
},
].concat((actionName && action) ? [{
actions: {
content: [
m('.flex'),
m(Button, {
label: actionName,
inactive: !actionActive || !action,
events: { onclick: action },
}),
],
},
}] : []),
});
}
}
/* https://css-tricks.com/snippets/css/complete-guide-grid */
/* https://css-tricks.com/snippets/css/a-guide-to-flexbox */
body {
/* Remove any browser-default margins. */
margin: 0;
padding: 0;
/* Height and width fallback for older browsers. */
min-height: 100%;
width: 100%;
/* Set the height to match that of the viewport. */
min-height: 100vh;
/* Set the width to match that of the viewport. */
width: 100vw;
/* Color */
background-color: GhostWhite;
/* Grid power! */
display: grid;
grid-template-columns: [container-start] 5% [header-start sidebar-start] auto
[sidebar-end content-start] auto
[header-end content-end] 5% [container-end];
grid-template-rows: [header-start] auto [header-end] auto
[content-start] 1fr [content-end];
grid-column-gap: 0px;
grid-row-gap: 0px;
}
/* Use the ::before pseudo element to insert background as first element */
body::before {
content: ' ';
grid-column: container-start / container-end;
grid-row: header-start / header-end;
background-color: rgb(32, 45, 84);
}
header {
grid-column: header-start / header-end;
grid-row: header-start / header-end;
/* Flex */
display: flex;
padding: 0.5em;
min-height: 8em;
color: white;
}
.header-logo {
flex-grow: 1;
flex-basis: 0;
text-align: left;
}
.header-logo-image {
height: 100%;
max-width: 100%;
}
.header-admin-switch {
flex-grow: 1.5;
flex-basis: 0;
margin-left: 2em;
margin-right: 2em;
align-self: center;
text-align: left;
}
.header-api-logout {
flex-grow: 1;
flex-basis: 0;
align-self: center;
text-align: right;
}
main {
grid-column: content-start / content-end;
grid-row: content-start / content-end;
padding: 0.5em;
}
aside {
grid-column: sidebar-start / sidebar-end;
grid-row: content-start / content-end;
padding: 0.5em;
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment