Commit ab848611 authored by Lasse Overgaard Møldrup's avatar Lasse Overgaard Møldrup
Browse files

Merge: Implemented grid mockup

parent 1e2fddf1
......@@ -9,7 +9,8 @@
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0"
"vue-router": "^4.0.0-0",
"vue-svg-inline-plugin": "^2.2.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
......@@ -7959,6 +7960,11 @@
"node": ">=6"
}
},
"node_modules/intersection-observer": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.0.tgz",
"integrity": "sha512-2Vkz8z46Dv401zTWudDGwO7KiGHNDkMv417T5ItcNYfmvHR/1qCTVBO9vwH8zZmQ0WkA/1ARwpysR9bsnop4NQ=="
},
"node_modules/ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
......@@ -13964,6 +13970,16 @@
"integrity": "sha1-M7QHd3VMZDJXPBIMw4CLvRDUfwQ=",
"dev": true
},
"node_modules/vue-svg-inline-plugin": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/vue-svg-inline-plugin/-/vue-svg-inline-plugin-2.2.0.tgz",
"integrity": "sha512-IgSs4csRkcxB1JqIpUgkXRjW4n7V1rZvC3AR1upnO/MPmC1GlnQ8DDsCV5S1r770PeLvppd2RhluLci/rUDjRw==",
"dependencies": {
"core-js": "^3.8.3",
"intersection-observer": "^0.12.0",
"whatwg-fetch": "^3.5.0"
}
},
"node_modules/vue-template-es2015-compiler": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
......@@ -14885,6 +14901,11 @@
"node": ">=0.8.0"
}
},
"node_modules/whatwg-fetch": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz",
"integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA=="
},
"node_modules/which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
......@@ -21754,6 +21775,11 @@
}
}
},
"intersection-observer": {
"version": "0.12.0",
"resolved": "https://registry.npmjs.org/intersection-observer/-/intersection-observer-0.12.0.tgz",
"integrity": "sha512-2Vkz8z46Dv401zTWudDGwO7KiGHNDkMv417T5ItcNYfmvHR/1qCTVBO9vwH8zZmQ0WkA/1ARwpysR9bsnop4NQ=="
},
"ip": {
"version": "1.1.5",
"resolved": "https://registry.npmjs.org/ip/-/ip-1.1.5.tgz",
......@@ -23935,6 +23961,67 @@
}
}
},
"postcss-modules": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules/-/postcss-modules-4.0.0.tgz",
"integrity": "sha512-ghS/ovDzDqARm4Zj6L2ntadjyQMoyJmi0JkLlYtH2QFLrvNlxH5OAVRPWPeKilB0pY7SbuhO173KOWkPAxRJcw==",
"dev": true,
"requires": {
"generic-names": "^2.0.1",
"icss-replace-symbols": "^1.1.0",
"lodash.camelcase": "^4.3.0",
"postcss-modules-extract-imports": "^3.0.0",
"postcss-modules-local-by-default": "^4.0.0",
"postcss-modules-scope": "^3.0.0",
"postcss-modules-values": "^4.0.0",
"string-hash": "^1.1.1"
},
"dependencies": {
"icss-utils": {
"version": "5.1.0",
"resolved": "https://registry.npmjs.org/icss-utils/-/icss-utils-5.1.0.tgz",
"integrity": "sha512-soFhflCVWLfRNOPU3iv5Z9VUdT44xFRbzjLsEzSr5AQmgqPMTHdU3PMT1Cf1ssx8fLNJDA1juftYl+PUcv3MqA==",
"dev": true,
"requires": {}
},
"postcss-modules-extract-imports": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-3.0.0.tgz",
"integrity": "sha512-bdHleFnP3kZ4NYDhuGlVK+CMrQ/pqUm8bx/oGL93K6gVwiclvX5x0n76fYMKuIGKzlABOy13zsvqjb0f92TEXw==",
"dev": true,
"requires": {}
},
"postcss-modules-local-by-default": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-local-by-default/-/postcss-modules-local-by-default-4.0.0.tgz",
"integrity": "sha512-sT7ihtmGSF9yhm6ggikHdV0hlziDTX7oFoXtuVWeDd3hHObNkcHRo9V3yg7vCAY7cONyxJC/XXCmmiHHcvX7bQ==",
"dev": true,
"requires": {
"icss-utils": "^5.0.0",
"postcss-selector-parser": "^6.0.2",
"postcss-value-parser": "^4.1.0"
}
},
"postcss-modules-scope": {
"version": "3.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-scope/-/postcss-modules-scope-3.0.0.tgz",
"integrity": "sha512-hncihwFA2yPath8oZ15PZqvWGkWf+XUfQgUGamS4LqoP1anQLOsOJw0vr7J7IwLpoY9fatA2qiGUGmuZL0Iqlg==",
"dev": true,
"requires": {
"postcss-selector-parser": "^6.0.4"
}
},
"postcss-modules-values": {
"version": "4.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-values/-/postcss-modules-values-4.0.0.tgz",
"integrity": "sha512-RDxHkAiEGI78gS2ofyvCsu7iycRv7oqw5xMWn9iMoR0N/7mf9D50ecQqUo5BZ9Zh2vH4bCUR/ktCqbB9m8vJjQ==",
"dev": true,
"requires": {
"icss-utils": "^5.0.0"
}
}
}
},
"postcss-modules-extract-imports": {
"version": "2.0.0",
"resolved": "https://registry.npmjs.org/postcss-modules-extract-imports/-/postcss-modules-extract-imports-2.0.0.tgz",
......@@ -26668,6 +26755,16 @@
}
}
},
"vue-svg-inline-plugin": {
"version": "2.2.0",
"resolved": "https://registry.npmjs.org/vue-svg-inline-plugin/-/vue-svg-inline-plugin-2.2.0.tgz",
"integrity": "sha512-IgSs4csRkcxB1JqIpUgkXRjW4n7V1rZvC3AR1upnO/MPmC1GlnQ8DDsCV5S1r770PeLvppd2RhluLci/rUDjRw==",
"requires": {
"core-js": "^3.8.3",
"intersection-observer": "^0.12.0",
"whatwg-fetch": "^3.5.0"
}
},
"vue-template-es2015-compiler": {
"version": "1.9.1",
"resolved": "https://registry.npmjs.org/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz",
......@@ -27397,6 +27494,11 @@
"integrity": "sha512-OqedPIGOfsDlo31UNwYbCFMSaO9m9G/0faIHj5/dZFDMFqPTcx6UwqyOy3COEaEOg/9VsGIpdqn62W5KhoKSpg==",
"dev": true
},
"whatwg-fetch": {
"version": "3.6.2",
"resolved": "https://registry.npmjs.org/whatwg-fetch/-/whatwg-fetch-3.6.2.tgz",
"integrity": "sha512-bJlen0FcuU/0EMLrdbJ7zOnW6ITZLrZMIarMUVmdKtsGvZna8vxKYaexICWPfZ8qwf9fzNq+UEIZrnSaApt6RA=="
},
"which": {
"version": "1.3.1",
"resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz",
......@@ -10,7 +10,8 @@
"dependencies": {
"core-js": "^3.6.5",
"vue": "^3.0.0",
"vue-router": "^4.0.0-0"
"vue-router": "^4.0.0-0",
"vue-svg-inline-plugin": "^2.2.0"
},
"devDependencies": {
"@vue/cli-plugin-babel": "~4.5.0",
......
......@@ -20,6 +20,8 @@
</script>
<style lang="scss">
$text-color: #272b30;
body, html {
height: 100%;
margin: 0;
......@@ -29,12 +31,21 @@
box-sizing: border-box;
}
a {
color: $text-color;
&:hover, &:focus {
color: #42b983
}
}
#app {
font-family: Avenir, Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
color: $text-color;
background-color: #e7ede8;
height: 100%;
}
......
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 119.72" style="enable-background:new 0 0 122.88 119.72" xml:space="preserve"><g><path d="M22.72,0h77.45c6.25,0,11.93,2.56,16.05,6.67c4.11,4.11,6.67,9.79,6.67,16.05v74.29c0,6.25-2.56,11.93-6.67,16.05 l-0.32,0.29c-4.09,3.94-9.64,6.38-15.73,6.38H22.72c-6.25,0-11.93-2.56-16.05-6.67l-0.3-0.32C2.43,108.64,0,103.09,0,97.01V22.71 c0-6.25,2.55-11.93,6.67-16.05C10.78,2.55,16.46,0,22.72,0L22.72,0z M55.47,38.34c0-3.3,2.67-5.97,5.97-5.97 c3.3,0,5.97,2.67,5.97,5.97v15.55h15.55c3.3,0,5.97,2.67,5.97,5.97c0,3.3-2.67,5.97-5.97,5.97H67.41v15.55 c0,3.3-2.67,5.97-5.97,5.97c-3.3,0-5.97-2.67-5.97-5.97V65.83H39.91c-3.3,0-5.97-2.67-5.97-5.97c0-3.3,2.67-5.97,5.97-5.97h15.55 V38.34L55.47,38.34z M100.16,10.24H22.72c-3.43,0-6.54,1.41-8.81,3.67c-2.26,2.26-3.67,5.38-3.67,8.81v74.29 c0,3.33,1.31,6.35,3.43,8.59l0.24,0.22c2.26,2.26,5.38,3.67,8.81,3.67h77.45c3.32,0,6.35-1.31,8.59-3.44l0.21-0.23 c2.26-2.26,3.67-5.38,3.67-8.81V22.71c0-3.42-1.41-6.54-3.67-8.81C106.71,11.65,103.59,10.24,100.16,10.24L100.16,10.24z"/></g></svg>
\ No newline at end of file
<?xml version="1.0" encoding="utf-8"?><svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewBox="0 0 122.88 122.879" enable-background="new 0 0 122.88 122.879" xml:space="preserve"><g><path d="M61.44,0c16.96,0,32.328,6.882,43.453,17.986c11.104,11.125,17.986,26.494,17.986,43.453 c0,16.961-6.883,32.328-17.986,43.453C93.769,115.998,78.4,122.879,61.44,122.879c-16.96,0-32.329-6.881-43.454-17.986 C6.882,93.768,0,78.4,0,61.439C0,44.48,6.882,29.111,17.986,17.986C29.112,6.882,44.48,0,61.44,0L61.44,0z M73.452,39.152 c2.75-2.792,7.221-2.805,9.986-0.026c2.764,2.776,2.775,7.292,0.027,10.083L71.4,61.445l12.077,12.25 c2.728,2.77,2.689,7.256-0.081,10.021c-2.772,2.766-7.229,2.758-9.954-0.012L61.445,71.541L49.428,83.729 c-2.75,2.793-7.22,2.805-9.985,0.025c-2.763-2.775-2.776-7.291-0.026-10.082L51.48,61.435l-12.078-12.25 c-2.726-2.769-2.689-7.256,0.082-10.022c2.772-2.765,7.229-2.758,9.954,0.013L61.435,51.34L73.452,39.152L73.452,39.152z M96.899,25.98C87.826,16.907,75.29,11.296,61.44,11.296c-13.851,0-26.387,5.611-35.46,14.685 c-9.073,9.073-14.684,21.609-14.684,35.459s5.611,26.387,14.684,35.459c9.073,9.074,21.609,14.686,35.46,14.686 c13.85,0,26.386-5.611,35.459-14.686c9.073-9.072,14.684-21.609,14.684-35.459S105.973,35.054,96.899,25.98L96.899,25.98z"/></g></svg>
\ No newline at end of file
......@@ -2,7 +2,7 @@
<div class="active-courses">
<h2>Aktive kurser</h2>
<ul>
<li v-for="(course, index) in courses" :key="index"><a href="#">{{ course }}</a></li>
<li v-for="(course, index) in courses" :key="index"><a href="/about">{{ course }}</a></li>
</ul>
</div>
</template>
......@@ -22,4 +22,8 @@ export default {
.active-courses {
@include block;
}
li {
margin: 10px 0;
}
</style>
\ No newline at end of file
<template>
<div class="deadlines">
<h2>Deadlines</h2>
<table>
<tr v-for="(deadline, index) in deadlines" :key="index">
<td class="course-name">{{ deadline.course }}</td>
<td class="handin-name"><a href="#">{{ deadline.name }}</a></td>
<td class="due-date">{{ deadline.date.toLocaleDateString('da-dk').replace(/\./g, '/') }}</td>
</tr>
</table>
<hr/>
<ul>
<li v-for="(deadline, index) in deadlines" :key="index">
<span class="course-name">{{ deadline.course }}</span>
<span class="due-date" :class="{ close: (deadline.date - new Date()) / (1000 * 60 * 60 * 24) < 1 }">
{{ deadline.date.toLocaleDateString('da-dk').replace(/\./g, '/') + ' ' + deadline.date.toLocaleTimeString('da-dk').slice(0, -3) }}
</span>
<br/>
<a class="handin-name" href="#">{{ deadline.name }}</a>
<hr/>
</li>
</ul>
</div>
</template>
......@@ -28,7 +33,15 @@ export default {
@include block;
}
td {
padding: 5px 10px;
.due-date {
float: right;
&.close {
color: rgb(220, 0, 0)
}
}
.handin-name {
font-size: 1.1em;
}
</style>
\ No newline at end of file
<template>
<div class="feed">
<h2>Feed</h2>
<ul>
<li v-for="(message, index) in messages" :key="index" @click="$router.push('/about')" @keypress.enter="$router.push('/about')" tabindex=0>
<a href="/about">{{ message.course }}</a>
<span class="msg-date">{{ message.date.toLocaleDateString('da-dk').replace(/\./g, '/') }}</span>
<p>{{ message.text }}</p>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Feed',
data() {
return {
messages: [
{
course: 'Calculus Beta',
date: new Date(),
text: 'Suspendisse at eros vel ligula sollicitudin dignissim. Morbi ligula metus, rhoncus at ultrices eget, ultricies quis ex. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia curae; Sed sit amet odio orci. Donec a velit at urna facilisis commodo nec a justo. Nulla facilisi. Nulla maximus fermentum.',
},
{
course: 'Databaser',
date: new Date(),
text: `It came to my attention that some students have been asking what the word "same" means in the expression "beverages of the same name".
It is natural that the expression "same" means "same", therefore the expression "beverages of the same name" denotes beverages of the same name.
Any assumption that the word "same" means "same or different" is wrong and cannot be taken as correct.`,
}
]
}
}
}
</script>
<style scoped lang="scss">
.feed {
@include block;
}
li {
border: solid 1px rgb(160, 160, 160);
padding: 5px;
&:hover, &:focus {
border-color: black;
cursor: pointer;
}
&:not(:last-child) {
margin-bottom: 20px;
}
}
.msg-date {
float: right;
}
p {
margin: 0.4em 0 0 0;
@include multiline-ellipsis($line-height: 1.2em, $line-count: 3)
}
</style>
\ No newline at end of file
<template>
<div class="mail">
<h2>Post</h2>
<hr/>
<ul>
<li v-for="(mail, index) in mails" :key="index">
<span>{{ mail.sender }}</span>
<span class="send-date">{{ mail.date.toLocaleDateString('da-dk').replace(/\./g, '/') }}</span>
<br/>
<a class="subject" href="/about">{{ mail.subject }}</a>
<hr/>
</li>
</ul>
</div>
</template>
<script>
export default {
name: 'Mail',
data() {
return {
mails: [
{
sender: 'henrikb@post.au.dk',
subject: 'TDD Break',
date: new Date(),
},
{
sender: '202201010@post.au.dk',
subject: 'I\'m from the future',
date: new Date(),
}
]
}
}
}
</script>
<style scoped lang="scss">
.mail {
@include block;
}
.send-date {
float: right;
}
.subject {
font-size: 1.1em;
}
</style>
\ No newline at end of file
import { createApp } from 'vue'
import App from './App.vue'
import router from './router'
import VueSvgInlinePlugin from 'vue-svg-inline-plugin';
createApp(App).use(router).mount('#app')
createApp(App)
.use(router)
.use(VueSvgInlinePlugin)
.mount('#app');
@mixin block {
width: 100%;
height: 100%;
border: 2px solid black;
border: 2px solid gray;
background-color: #fbfbfb;
text-align: left;
padding: 20px;
overflow-y: scroll;
h2 {
margin-top: 0;
}
ul {
list-style-type: none;
padding: 0;
margin: 0;
}
}
// https://hackingui.com/a-pure-css-solution-for-multiline-text-truncation/
@mixin multiline-ellipsis($line-height: 1.2em, $line-count: 1){
overflow: hidden;
position: relative;
line-height: $line-height;
max-height: $line-height * $line-count;
&:after {
content: "";
text-align: right;
position: absolute;
bottom: 0;
right: 0;
width: 150px;
height: 1.2em;
background: linear-gradient(to right, rgba(255, 255, 255, 0), rgba(255, 255, 255, 1) 70%);
}
}
\ No newline at end of file
......@@ -2,20 +2,27 @@
<div class="home">
<div id="grid">
<div v-for="side in ['left', 'right']" :key="side" :id="side + '-col'">
<div class="row" v-for="(row, index) in $data[side]" :key="index" :style="{ height: row.height + 'px' }">
<div v-for="(block, index) in row.blocks" :key="index" :style="{ flexBasis: block.width + '%' }">
<div class="row" v-for="(row, rowIndex) in $data[side]" :key="rowIndex" :style="{ height: row.height + 'px' }">
<div class="block" v-for="(block, colIndex) in row.blocks" :key="colIndex" :style="{ flexBasis: block.width + '%' }">
<component :is="block.type"></component>
<button class="remove-block" @click="removeBlock(side, rowIndex, colIndex)">
<img v-svg-inline class="icon" src="@/assets/cross.svg"/>
</button>
</div>
</div>
<button class="add-block" @click="addBlock(side)">Add block</button>
<button class="add-block" @click="addBlock(side)">
<img v-svg-inline class="icon" src="@/assets/collapse-plus.svg"/>
</button>
</div>
</div>
</div>
</template>
<script>
import ActiveCourses from "@/components/ActiveCourses";
import Deadlines from "@/components/Deadlines";
import ActiveCourses from "@/components/blocks/ActiveCourses";
import Deadlines from "@/components/blocks/Deadlines";
import Feed from "@/components/blocks/Feed";
import Mail from "@/components/blocks/Mail";
export default {
name: 'Home',
......@@ -28,18 +35,18 @@ export default {
blocks: [{ type: "ActiveCourses", width: 100 }],
},
{
height: 200,
height: 300,
blocks: [{ type: "Deadlines", width: 100 }],
}
],
right: [
{
height: 300,
blocks: [{ type: "ActiveCourses", width: 100 }],
height: 400,
blocks: [{ type: "Feed", width: 100 }],
},
{
height: 200,
blocks: [{ type: "ActiveCourses", width: 50 }, { type: "Deadlines", width: 50 }],
height: 330,
blocks: [{ type: "Feed", width: 50 }, { type: "Mail", width: 50 }],
},
]
}
......@@ -49,14 +56,22 @@ export default {
addBlock(side) {
this[side].push({
height: 200,
blocks: [{ type: "ActiveCourses", width: 100 }]
blocks: [{ type: "Feed", width: 100 }]
});
},
removeBlock(side, row, col) {
this[side][row].blocks.splice(col, 1);
if (this[side][row].blocks.length === 0)
this[side].splice(row, 1);
}
},
components: {
ActiveCourses,
Deadlines
Deadlines,
Feed,
Mail
}
}
</script>
......@@ -105,4 +120,59 @@ export default {
}
}
}
.block {
position: relative;
&:hover {
.remove-block {
display: block;
}
}
}
.remove-block {
display: none;
width: 30px;
height: 30px;
border: none;
background: none;
padding: 0;
position: absolute;
top: 10px;
right: 10px;
svg {
fill: rgb(165, 165, 165);
}
&:hover, &:focus {
cursor: pointer;
svg {
fill: #272b30;
}
}
}
.add-block {
width: 50px;
height: 50px;
border: none;
background: none;
padding: 0;
margin-top: $gap / 2;
svg {
fill: rgb(165, 165, 165);
}
&:hover, &:focus {
cursor: pointer;
svg {
fill: #272b30;
}
}
}
</style>
Supports Markdown
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