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

Merge branch 'develop' into 'feature/calendar-fix'

# Conflicts:
#   website/studerende-dk/src/components/blocks/Calendar.vue
parents d6e7bfc0 848114c2
Pipeline #52371 passed with stage
in 39 seconds
.DS_Store
\ No newline at end of file
.DS_Store
.vscode
\ No newline at end of file
stages:
- test
- create-vue-build
- build-docker-container
- build-docker-server-container
- build-docker-web-container
test:
stage: test
......@@ -16,7 +17,6 @@ test:
create-vue-build:
only:
# - master
- develop
stage: create-vue-build
image: node
......@@ -34,11 +34,26 @@ create-vue-build:
paths:
- website/studerende-dk/node_modules/
build-docker-container:
build-docker-server-container:
only:
# - master
- develop
stage: build-docker-container
stage: build-docker-server-container
image: docker:latest
services:
- name: docker:19.03.8-dind
before_script:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- cd backend
- echo "Starting docker build of server."
- docker build . -t "$CI_REGISTRY_IMAGE""/server"
- docker push "$CI_REGISTRY_IMAGE""/server"
- echo "Docker build of server done!"
build-docker-web-container:
only:
- develop
stage: build-docker-web-container
image: docker:latest
services:
- name: docker:19.03.8-dind
......@@ -46,5 +61,7 @@ build-docker-container:
- docker login -u "$CI_REGISTRY_USER" -p "$CI_REGISTRY_PASSWORD" $CI_REGISTRY
script:
- cd website/studerende-dk
- docker build . -t "$CI_REGISTRY_IMAGE"
- docker push "$CI_REGISTRY_IMAGE"
- echo "Starting docker build of web."
- docker build . -t "$CI_REGISTRY_IMAGE""/web"
- docker push "$CI_REGISTRY_IMAGE""/web"
- echo "Docker build of web done!"
FROM python:3.8
COPY server/* .
ENV PYTHONUNBUFFERED=1
EXPOSE 1337
CMD ["python", "server.py"]
\ No newline at end of file
# Inspired by https://pythonbasics.org/webserver/
from http.server import BaseHTTPRequestHandler, HTTPServer
import time
hostName = '0.0.0.0'
serverPort = 1337
db = {
'katrine-marie' : '{"left":[],"right":[{"height":400,"blocks":[{"type":"Calendar","width":100}]}]}',
'isaac' : '{"left":[],"right":[{"height":400,"blocks":[{"type":"Feed","width":100}]}]}'
}
class MyServer(BaseHTTPRequestHandler):
def _set_ok_headers(self):
self.send_response(200)
self.send_header('Content-type', 'text/html')
self.end_headers()
def _set_err_headers(self):
self.send_response(500)
self.send_header('Content-type', 'text/html')
self.end_headers()
def handle_load_layout(self, id):
if id in db:
self._set_ok_headers()
self.wfile.write(bytes(db[id], 'utf-8'))
else:
self._set_err_headers()
self.wfile.write(bytes('Error: Could not find id ' + str(id), 'utf-8'))
def handle_save_layout(self, id, data):
db[id] = data.replace('%22', '"')
self._set_ok_headers()
def do_GET(self):
# remove '/?' from path
query = self.path[2:]
fields = dict(f.split("=") for f in query.split("&"))
if fields['type'] == "load":
self.handle_load_layout(fields['id'])
elif fields['type'] == "save":
self.handle_save_layout(fields['id'], fields['data'])
else:
self._set_err_headers()
self.wfile.write(bytes('Request type not supported', 'utf-8'))
if __name__ == '__main__':
webServer = HTTPServer((hostName, serverPort), MyServer)
print('Server started http://%s:%s' % (hostName, serverPort))
try:
webServer.serve_forever()
except KeyboardInterrupt:
pass
webServer.server_close()
print('Server stopped.')
\ No newline at end of file
# From https://docs.docker.com/compose/
version: "3.9"
services:
web:
build: website/studerende-dk/
ports:
- "80:80"
server:
build: backend/
ports:
- "1337:1337"
\ No newline at end of file
#!/bin/bash
# this script pulls the docker images and
# deploys them respectively if they are
# newer than the ones running.
# this script can be run at any time,
# and will only change the running
# containers if newer ones are available.
function deploy {
local url=$1
local service_name=$2
local run_arguments=$3
old_digest=$(docker inspect -f '{{.RepoDigests}}' ${url}:active | grep -o 'sha256:[0-9A-Fa-f]*')
# probably no existing image
if [ $? -ne 0 ]; then
echo "No existing image! Abort."
exit 1;
fi
new_digest=$(docker pull ${url}:latest | grep Digest | sed 's/Digest: //')
# network error or authentication might go wrong
if [ $? -ne 0 ]; then
echo "Auth or network err! Abort."
exit 2;
fi
# sanity check that new digest is formatted correctly and is same length as old.
# if it aint, it could be the result of a gitlab server error or such.
local check=$(echo $new_digest | grep -o 'sha256:[0-9A-Fa-f]*')
if [ "${#check}" -eq "0" ] || [ ${#old_digest} -ne 71 ]; then
echo "Damnit, something went bad! Crash and burn.."
exit 3;
fi
echo "Old digest: $old_digest"
echo "New digest: $new_digest"
if [ "$old_digest" != "$new_digest" ]; then
echo "Deploying new docker instance: $service_name."
docker stop $service_name
docker rm $service_name
docker rmi ${url}:active
docker tag ${url}:latest ${url}:active
docker run --network persist-net $run_arguments --name $service_name -d ${url}:active
result=0
else
echo "Already up to date."
fi
# remove/untag file. silence output
docker rmi ${url}:latest >/dev/null 2>&1
}
base_url="registry.gitlab.au.dk/exsys2021/da6/hold-afstand/"
# deploy new server if available
result=1
deploy ${base_url}server "server" "--network-alias server"
server_deployed=$result
echo
# deploy new web if available
result=1
deploy ${base_url}web "web" "-p 80:80"
web_deployed=$result
# if anything has been deployed, notify the devs
if [ $server_deployed -eq 0 ] || [ $web_deployed -eq 0 ]; then
[ $server_deployed -eq 0 ] && msg="backend"
[ $web_deployed -eq 0 ] && [ $server_deployed -eq 0 ] && msg=${msg}" and "
[ $web_deployed -eq 0 ] && msg=${msg}"frontend"
slack_msg="A new version of the ${msg} has been deployed! Check it out: https://vm34.exsys2021.cs.au.dk/"
echo $slack_msg
# notify slack channel
/home/auuser/slack-notifier.sh $slack_msg
fi
echo "Done."
#!/bin/bash
# ----- CAUTION!!! -----
# This script stops and removes the running web and server
# containers, removes their images and the persist-net
# docker network.
#
# It then reconfigures the network, download
# the images and redeploys them again.
base_url="registry.gitlab.au.dk/exsys2021/da6/hold-afstand/"
# stops docker containers
echo -n "Stopping containers..."
docker stop server >/dev/null 2>&1
docker stop web >/dev/null 2>&1
echo " Done."
# removes docker containers
echo -n "Removing containers..."
docker rm server >/dev/null 2>&1
docker rm web >/dev/null 2>&1
echo " Done."
# removes docker images
echo -n "Removing images..."
docker rmi ${base_url}server:active >/dev/null 2>&1
docker rmi ${base_url}web:active >/dev/null 2>&1
echo " Done."
# removes unused docker networks
echo -n "Removing docker network..."
docker network rm persist-net >/dev/null 2>&1
echo " Done."
# pulling the images
echo -n "Pulling latest sever image..."
docker pull ${base_url}server:latest >/dev/null 2>&1
echo " Done."
echo -n "Pulling latest web image..."
docker pull ${base_url}web:latest >/dev/null 2>&1
echo " Done."
# changes tags from latest to active
echo -n "Tagging..."
docker tag ${base_url}server:latest ${base_url}server:active >/dev/null 2>&1
docker tag ${base_url}web:latest ${base_url}web:active >/dev/null 2>&1
docker rmi ${base_url}server:latest >/dev/null 2>&1
docker rmi ${base_url}web:latest >/dev/null 2>&1
echo " Done."
# crates network
echo -n "Creates docker network..."
docker network create -d bridge persist-net --attachable >/dev/null 2>&1
echo " Done."
# spins up containers
echo -n "Spinning up containers..."
docker run --network persist-net --network-alias server --name server -d ${base_url}server:active >/dev/null 2>&1
docker run --network persist-net -p 80:80 --name web -d ${base_url}web:active >/dev/null 2>&1
echo " Done."
echo "All done!"
#!/bin/bash
# INFO: This script should be placed in auuser 's homefolder!
# sanity check
if [ "$#" == "0" ]; then
echo "The message should be passed as an argument!"
exit 1
fi
data='{"text":"'"$@"'"}'
url=$(head -n 1 slack-url)
curl -X POST -H 'Content-type: application/json' --data "$data" $url
FROM nginx:latest
COPY ./dist /usr/share/nginx/html
COPY nginx-conf/ /etc/nginx/conf.d/
\ No newline at end of file
##
# You should look at the following URL's in order to grasp a solid understanding
# of Nginx configuration files in order to fully unleash the power of Nginx.
# https://www.nginx.com/resources/wiki/start/
# https://www.nginx.com/resources/wiki/start/topics/tutorials/config_pitfalls/
# https://wiki.debian.org/Nginx/DirectoryStructure
#
# In most cases, administrators will remove this file from sites-enabled/ and
# leave it as reference inside of sites-available where it will continue to be
# updated by the nginx packaging team.
#
# This file will automatically load configuration files provided by other
# applications, such as Drupal or Wordpress. These applications will be made
# available underneath a path with that package name, such as /drupal8.
#
# Please see /usr/share/doc/nginx-doc/examples/ for more detailed examples.
##
# Default server configuration
#
server {
listen 80 default_server;
listen [::]:80 default_server;
# SSL configuration
#
# listen 443 ssl default_server;
# listen [::]:443 ssl default_server;
#
# Note: You should disable gzip for SSL traffic.
# See: https://bugs.debian.org/773332
#
# Read up on ssl_ciphers to ensure a secure configuration.
# See: https://bugs.debian.org/765782
#
# Self signed certs generated by the ssl-cert package
# Don't use them in a production server!
#
# include snippets/snakeoil.conf;
root /usr/share/nginx/html;
# Add index.php to the list if you are using PHP
index index.html index.htm index.nginx-debian.html;
server_name _;
location /persistence/ {
proxy_set_header X-NginX-Proxy true;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_pass http://server:1337/;
proxy_redirect off;
}
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
}
# pass PHP scripts to FastCGI server
#
#location ~ \.php$ {
# include snippets/fastcgi-php.conf;
#
# # With php-fpm (or other unix sockets):
# fastcgi_pass unix:/var/run/php/php7.4-fpm.sock;
# # With php-cgi (or other tcp sockets):
# fastcgi_pass 127.0.0.1:9000;
#}
# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#location ~ /\.ht {
# deny all;
#}
}
# Virtual Host configuration for example.com
#
# You can move that to a different file under sites-available/ and symlink that
# to sites-enabled/ to enable it.
#
#server {
# listen 80;
# listen [::]:80;
#
# server_name example.com;
#
# root /var/www/example.com;
# index index.html;
#
# location / {
# try_files $uri $uri/ =404;
# }
#}
\ No newline at end of file
<template>
<BlockTemplate heading="Aktive kurser">
<BlockTemplate heading="Aktive kurser" :row="row" :col="col">
<ul>
<li v-for="(course, index) in courses" :key="index"><a href="/about">{{ course }}</a></li>
</ul>
......@@ -9,10 +9,19 @@
<script>
export default {
name: 'ActiveCourses',
props: ['row', 'col'],
data() {
return {
courses: ['Calculus Beta', 'Databaser', 'etc.']
}
}
}
</script>
\ No newline at end of file
</script>
<style scoped lang="scss">
.block{
min-width: 250px;
}
</style>
\ No newline at end of file
<template>
<div class="block">
<div class="heading">
<div class="heading" :draggable="dragEnabled.value" @dragstart="startDrag($event, row, col)" @dragend.prevent="stopDrag()">
<h2>{{ heading }}</h2>
</div>
<div class="content">
......@@ -11,7 +11,9 @@
<script>
export default {
props: [ 'heading' ]
props: [ 'heading', 'row', 'col' ],
inject: [ 'dragEnabled', 'startDrag', 'stopDrag' ]
}
</script>
......@@ -21,6 +23,7 @@ export default {
.block {
width: 100%;
height: 100%;
min-width: 150px;
text-align: left;
display: flex;
flex-direction: column;
......@@ -29,6 +32,7 @@ export default {
.heading {
color: $lightest-theme-color;
background-color: $theme-color;
cursor: move;
h2 {
padding: 10px $padding;
......
<template>
<div id="calendar">
<table id="calendarTable">
<thead>
<thead :draggable="dragEnabled.value" @dragstart="startDrag($event, row, col)" @dragend.prevent="stopDrag()">
<!-- Generating first header of schema -->
<tr>
<th id="calendarHead" colspan="6">
......@@ -64,6 +64,11 @@
<script>
export default {
name: 'Cal',
props: ['row', 'col'],
inject: [ 'dragEnabled', 'startDrag', 'stopDrag' ],
data() {
return {
// Currently showing schema data
......@@ -276,6 +281,7 @@ export default {
</script>
<style lang="scss" scoped>
table{
width: 100%;
height: 100%;
......@@ -283,6 +289,9 @@ export default {
thead{
border: 0;
padding: 0;
height: 100%;
cursor: move;
tr{
&:first-of-type{
......@@ -426,6 +435,7 @@ export default {
}
#calendar{
min-width: 250px;
width: 100%;
height: 100%;
position: relative;
......
<template>
<BlockTemplate heading="Deadlines">
<BlockTemplate heading="Deadlines" :row="row" :col="col">
<ul>
<li v-for="(deadline, index) in deadlines" :key="index">
<span class="course-name">{{ deadline.course }}</span>
......@@ -15,19 +15,38 @@
</template>
<script>
Date.prototype.addDays = function(days) {
const date = new Date(this.valueOf());
date.setDate(date.getDate() + days);
return date;
}
Date.prototype.toMidnight = function() {
const date = new Date(this.valueOf());
date.setHours(0, 0, 0, 0);
return date;
}
export default {
name: 'Deadlines',
props: ['row', 'col'],
data() {
return {
deadlines: [{ course: "Calculus Beta", name: "Aflevering 1", date: new Date() },
{ course: "Databaser", name: "SQL", date: new Date("10 Apr 2021") },
{ course: "Numerisk Lineær Algebra", name: "Python for dummies", date: new Date("12 Apr 2021") }]
{ course: "Databaser", name: "SQL", date: new Date().addDays(2).toMidnight() },
{ course: "Numerisk Lineær Algebra", name: "Python for dummies", date: new Date().addDays(3).toMidnight() }]
}
}
}
</script>
<style scoped lang="scss">
.block{
min-width: 350px;
}
ul {
margin-top: 8px;
}
......
<template>
<BlockTemplate heading="Feed">
<BlockTemplate heading="Feed" :row="row" :col="col">
<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>
......@@ -13,6 +13,9 @@
<script>
export default {
name: 'Feed',
props: ['row', 'col'],
data() {
return {
messages: [
......@@ -37,6 +40,10 @@ Any assumption that the word "same" means "same or different" is wrong and canno
</script>
<style scoped lang="scss">
.block{
min-width: 250px;
}
ul {
padding: 20px;
}
......
<template>
<BlockTemplate heading="Post">
<BlockTemplate heading="Post" :row="row" :col="col">
<ul>
<li v-for="(mail, index) in mails" :key="index">
<span>{{ mail.sender }}</span>
<span style="width: 50%;">{{ mail.sender }}</span>
<span class="send-date">{{ mail.date.toLocaleDateString('da-dk').replace(/\./g, '/') }}</span>
<br/>
<a class="subject" href="/about">{{ mail.subject }}</a>
......@@ -15,6 +15,9 @@