61 Commits

Author SHA1 Message Date
7712419e9b Initial nix package build. Update composer 2023-10-01 03:33:56 +02:00
0da5d44ea1 Manually cast door state to int () 2023-09-12 20:31:14 +02:00
133c4e269d Re-enable recurring events for Fall 2023 () 2023-09-02 21:25:07 +02:00
850c8da95a Initial nix flake, automate devshell () 2023-09-02 19:55:24 +02:00
1ae6356aa5 Update contact information ()
* Update contact information

* Minor fixes to contact page

---------

Co-authored-by: Felix Albrigtsen <felix@albrigtsen.it>
2023-08-20 01:31:53 +02:00
fa4fa9ad7d Stop bots scraping mediawiki special pages/diffs/history () 2023-06-14 23:26:28 +02:00
d43e5faf3c Summer break; Disable recurring events () 2023-06-11 22:19:14 +02:00
57055c9c6f Fix previous merge ()
The previous merge contained a commit and a revert, but the original change remained on master.
2023-04-27 16:05:14 +02:00
5fbc1dbc00 Re-enable brettspillkveld ()
* Re-add brettspillkveld

Plz fix 
2023-04-27 16:01:40 +02:00
e364a5fee0 Stop including BrettspillActivity ()
Temporary until april 23
2023-04-17 01:21:15 +02:00
a4a6553329 Merge pull request from Programvareverkstedet/add-thunderbird-autoconfig
Add thunderbird autoconfig to .well-known
2023-02-25 23:28:10 +01:00
ae81d269fa Add thunderbird autoconfig to .well-known
This file will make it easier for people to set up thunderbird with a
pvv mail.

Relevant links:
- https://wiki.mozilla.org/Thunderbird:Autoconfiguration
- https://wiki.mozilla.org/Thunderbird:Autoconfiguration:ConfigFileFormat
2023-02-25 23:10:34 +01:00
31d9a955df Merge pull request from Programvareverkstedet/patch
Various patches; Fix admin groups, update deps
2023-01-19 13:58:10 +01:00
6bd3ce7731 Add notice on empty image gallery 2023-01-19 13:46:39 +01:00
9f45271b18 Update deprecated template syntax 2023-01-19 11:28:29 +01:00
567962c947 Fix admins addGroup and removeGroup, missing parameter 2023-01-19 11:27:48 +01:00
7defd8b388 Update minor dependency changes 2023-01-19 11:26:56 +01:00
a7f2c4f2d3 Merge pull request from Programvareverkstedet/linkdash 2023-01-16 16:27:28 +01:00
847fe67534 Merge pull request from Programvareverkstedet/2023events 2023-01-16 16:26:01 +01:00
79854aee6f Improved linkdash-minecraft-map 2023-01-16 16:22:53 +01:00
699876405c Inverted week offset on recurring events 2023-01-16 16:20:54 +01:00
a734fe6bd3 Add brettspill, drift and hack activities 2023-01-16 14:18:30 +01:00
c33736a501 Fix minecraft map link 2023-01-16 14:09:09 +01:00
3a39ca0f73 Merge pull request from Programvareverkstedet/linkdash
Add wrapper to services page, fix css and favicon
2022-11-29 17:56:29 +01:00
d8f8aafdd9 Add wrapper to services page, fix css and favicon 2022-11-29 17:52:39 +01:00
79ffb1fff5 Merge pull request from Programvareverkstedet/linkdash
Fix top margin on services
2022-11-29 17:35:56 +01:00
29c4c67645 Fix top margin on services 2022-11-29 17:31:22 +01:00
98da6ada23 Merge pull request from Programvareverkstedet/linkdash
Added linkdash - list of our services
2022-11-29 17:26:10 +01:00
1c1656c3bc Added photo gallery to services list 2022-11-29 17:14:03 +01:00
c489f303ea Add services, fix column styling 2022-11-29 17:07:36 +01:00
fc0286c277 Merge pull request from Programvareverkstedet/calenderFix
Disabled brettspillkveld and hackekveld
2022-11-27 10:14:21 +01:00
f4407fde4a Disabled brettspillkveld and hackekveld 2022-11-19 21:23:41 +01:00
9f11d442fe Merge pull request from Programvareverkstedet/video-til-karusell
Replace promo video with slideshow
2022-11-05 20:51:12 +01:00
1bc41124c0 Replace promo video with slideshow 2022-11-05 19:06:22 +01:00
72fb9e9915 Merge pull request from Programvareverkstedet/brettspillkveld
Added brettspillkveld
2022-09-24 22:05:21 +02:00
b555f915a0 Added brettspillkveld 2022-09-24 21:58:28 +02:00
4b9957e9c5 Add more services, make two columns 2022-09-18 01:24:57 +02:00
b42214b404 Establish layout for /tjenester 2022-09-17 17:09:35 +02:00
fcef05d439 Merge pull request from Programvareverkstedet/calendar-changes
Add driftkveld and hackekveld
2022-09-04 00:56:41 +02:00
0f8b15715b Add driftkveld and hackekveld 2022-09-04 00:53:30 +02:00
8a79d9d016 Merge pull request from Programvareverkstedet/video-embed
Replace old promo-video in /om/
2022-08-09 21:17:18 +02:00
f507b0cddd Replace old promo-video in /om/ 2022-08-09 20:53:24 +02:00
0b25f8d54a Merge pull request from Programvareverkstedet/video-embed
Front page: Fix missing closing tag
2022-08-08 19:55:44 +02:00
4f504e9456 Fix missing closing tag 2022-08-08 19:53:37 +02:00
1f32c03d86 Merge pull request from Programvareverkstedet/video-embed
Replace slideshow with promo video
2022-08-08 17:24:53 +02:00
fc6d5d5f8e Update CSS to preserve video aspect ratio 2022-08-08 16:36:58 +02:00
1cde0a2a93 Replace slideshow with promo video 2022-08-08 15:43:23 +02:00
65c0bad9b0 Merge pull request from Programvareverkstedet/calendarChanges
Removed driftskveld
2022-05-26 16:16:52 +02:00
9fa6066724 Removed driftskveld temporarily 2022-05-26 14:08:41 +02:00
a506dc44cc Merge pull request from Programvareverkstedet/origin/calendarChanges
Removed hackekveld temporarily
2022-03-26 20:39:46 +01:00
a80114be7a Removed hackekveld temporarily 2022-03-26 20:34:05 +01:00
ab6edd92e1 Merge pull request from Programvareverkstedet/calendarChanges
Lagt til hackekveld fjerdehver uke
2022-03-15 13:11:13 +01:00
6070cf4bd3 Lagt til hackekveld fjerdehver uke 2022-02-17 16:04:42 +01:00
fdd1d12e9e allow uppercase file extensions 2022-01-31 12:32:33 +01:00
6cae4cb0e2 :) 2022-01-29 22:54:52 +01:00
15c9431c10 remove nerdepitsa
no-one whent there
2022-01-29 19:34:13 +01:00
500ea63c77 Merge pull request from Programvareverkstedet/AddDriftkveld
Added biweekly driftkveld
2022-01-29 19:33:54 +01:00
bbe51e702b Added biweekly driftkveld 2022-01-29 19:21:16 +01:00
ab1bbdd3df Forgot login 2022-01-25 16:23:14 +01:00
893f57c9b7 Forgot to remove line 2022-01-25 15:08:37 +01:00
184d40266b Clarify dependencies 2022-01-25 15:06:27 +01:00
43 changed files with 2107 additions and 903 deletions

@@ -2,6 +2,6 @@
FROM php:7.4-cli
RUN apt-get update && \
apt-get install -y \
sqlite \
sqlite3 \
unzip \
git

@@ -13,7 +13,9 @@ Put it in a folder your webserver can find.
Make sure you have `sqlite3`, `php` and `pdo-sqlite` installed.
These can be obtained from your package manager.
Then make sure PHP has the `curl`, `pdo-sqlite` and `sqlite3` extensions enabled, see `/etc/php/php.ini`.
Then make sure PHP has the `curl`, `pdo-sqlite`, `ext-dom` and `sqlite3` extensions enabled, see `/etc/php/php.ini`.
To install all mentioned requirements on debian: `apt install composer sqlite3 php8.1-sqlite3 simplesamlphp php-xml`, followed by `composer update`.
./dev.sh

@@ -1,9 +1,16 @@
{
"name": "programvareverkstedet/nettsiden",
"description": "Programvareverkstedets public website",
"require": {
"simplesamlphp/simplesamlphp": "~1",
"erusev/parsedown": "^1.7"
},
"require-dev": {
"ext-pdo_sqlite": "*"
},
"config": {
"allow-plugins": {
"simplesamlphp/composer-module-installer": true
}
}
}

2104
composer.lock generated

File diff suppressed because it is too large Load Diff

2
dev.sh

@@ -17,7 +17,7 @@ if test ! -d vendor; then
php composer.phar install || exit $?
cp -v dist/authsources_example.php vendor/simplesamlphp/simplesamlphp/config/authsources.php
cp -v dist/saml20-idp-remote.php vendor/simplesamlphp/simplesamlphp/metadata/saml20-idp-remote.php
# cp -v vendor/simplesamlphp/simplesamlphp/config-templates/config.php vendor/simplesamlphp/simplesamlphp/config/config.php
cp -v vendor/simplesamlphp/simplesamlphp/config-templates/config.php vendor/simplesamlphp/simplesamlphp/config/config.php
sed -e "s/'trusted.url.domains' => array()/'trusted.url.domains' => array('localhost:1080')/g" < vendor/simplesamlphp/simplesamlphp/config-templates/config.php > vendor/simplesamlphp/simplesamlphp/config/config.php
ln -s ../vendor/simplesamlphp/simplesamlphp/www/ www/simplesaml
fi

27
flake.lock generated Normal file

@@ -0,0 +1,27 @@
{
"nodes": {
"nixpkgs": {
"locked": {
"lastModified": 1695978539,
"narHash": "sha256-lta5HToBZMWZ2hl5CautNSUgIZViR41QxN7JKbMAjgQ=",
"owner": "NixOS",
"repo": "nixpkgs",
"rev": "bd9b686c0168041aea600222be0805a0de6e6ab8",
"type": "github"
},
"original": {
"owner": "NixOS",
"ref": "nixpkgs-unstable",
"repo": "nixpkgs",
"type": "github"
}
},
"root": {
"inputs": {
"nixpkgs": "nixpkgs"
}
}
},
"root": "root",
"version": 7
}

71
flake.nix Normal file

@@ -0,0 +1,71 @@
{
description = "Programvareverkstedet/nettsiden PHP environment";
inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixpkgs-unstable";
};
outputs = { self, nixpkgs }:
let
systems = [
"x86_64-linux"
"aarch64-linux"
"aarch64-darwin"
];
forAllSystems = f: nixpkgs.lib.genAttrs systems (system: f system);
in {
packages = forAllSystems (system: rec {
pkgs = import nixpkgs { inherit system; };
default = pkgs.callPackage ./package.nix { php = pkgs.php82; };
});
devShells = forAllSystems (system: rec {
pkgs = import nixpkgs { inherit system; };
default = pkgs.mkShellNoCC {
buildInputs = with pkgs; [
php82
(with php82Extensions; [
iconv
mbstring
pdo_mysql
pdo_sqlite
])
sqlite
git
];
shellHook = ''
export PHPHOST=localhost
export PHPPORT=1080
alias runDev='php -S $PHPHOST:$PHPPORT -d error_reporting=E_ALL -d display_errors=1 -t www/'
# Prepare dev environment with sqlite and config files
test -e pvv.sqlite || sqlite3 pvv.sqlite < dist/pvv.sql
test -e sql_config.php || cp -v dist/sql_config_example.php sql_config.php
test -e dataporten_config.php || cp -v dist/dataporten_config.php dataporten_config.php
test -e composer.phar || curl -O https://getcomposer.org/composer.phar
if [ ! -f lib/OAuth2-Client/OAuth2Client.php ] ; then
echo Missing git submodules. Installing...
(set -x; git submodule update --init --recursive) || exit $?
fi
if [ ! -d vendor ] ; then
php composer.phar install || exit $?
cp -v dist/authsources_example.php vendor/simplesamlphp/simplesamlphp/config/authsources.php
cp -v dist/saml20-idp-remote.php vendor/simplesamlphp/simplesamlphp/metadata/saml20-idp-remote.php
cp -v vendor/simplesamlphp/simplesamlphp/config-templates/config.php vendor/simplesamlphp/simplesamlphp/config/config.php
sed -e "s/'trusted.url.domains' => array()/'trusted.url.domains' => array(\"$PHPHOST:$PHPPORT\")/g" < vendor/simplesamlphp/simplesamlphp/config-templates/config.php > vendor/simplesamlphp/simplesamlphp/config/config.php
ln -s ../vendor/simplesamlphp/simplesamlphp/www/ www/simplesaml
fi
'';
# TODO:
# - Integrate with docker config
# - Make "trusted.url.domains" dynamic based on the current host:port
# - Do not download composer.phar with curl
};
});
};
}

@@ -25,10 +25,12 @@ $as = new SimpleSAML_Auth_Simple($sp);
use \pvv\side\Agenda;
$agenda = new \pvv\side\Agenda([
new \pvv\side\social\NerdepitsaActivity,
// new \pvv\side\social\AnimekveldActivity,
// new \pvv\side\social\DriftkveldActivity,
new \pvv\side\DBActivity($pdo),
]);
// new \pvv\side\social\NerdepitsaActivity,
// new \pvv\side\social\AnimekveldActivity,
new \pvv\side\social\HackekveldActivity,
new \pvv\side\social\BrettspillActivity,
new \pvv\side\social\DriftkveldActivity,
new \pvv\side\DBActivity($pdo),
]);
$months_translations = ['januar', 'februar', 'mars', 'april', 'mai', 'juni', 'juli', 'august', 'september', 'oktober', 'november', 'desember'];

@@ -9,10 +9,10 @@ function navbar($depth, $active = NULL) {
'Prosjekter' => 'prosjekt',
'Kontakt' => 'kontakt',
'Webmail' => 'mail',
//'Webmail' => 'https://webmail.pvv.ntnu.no/',
'Galleri' => 'galleri',
'Wiki' => 'pvv',
'Git' => 'https://git.pvv.ntnu.no/',
'Tjenester' => 'tjenester',
];
foreach($menuItems as $caption => $link) {
$isActive = $active === $link;
@@ -51,17 +51,17 @@ function loginBar($sp = null, $pdo = null) {
$userManager = new \pvv\admin\UserManager($pdo);
$isAdmin = $userManager->isAdmin($uname);
}
$result .= "\t<a id=\"login\" href=\"#usermenu\" aria-hidden=\"true\">${svg}" . htmlspecialchars($uname) . "</a>\n";
$result .= "\t<a id=\"login\" href=\"#usermenu\" aria-hidden=\"true\">{$svg}" . htmlspecialchars($uname) . "</a>\n";
$result .= "\n\t<ul id=\"usermenu\">\n";
$result .= "\n\t\t<li><a id=\"login\" href=\"#\">${svg}" . htmlspecialchars($uname) . "</a></li>\n";
$result .= "\n\t\t<li><a id=\"login\" href=\"#\">{$svg}" . htmlspecialchars($uname) . "</a></li>\n";
if ($isAdmin) {
$result .= "\n\t\t<li><a href=\"/admin/\">Admin</a></li>\n";
}
$result .= "\n\t\t<li><a href=\"" . htmlspecialchars($as->getLogoutURL()) . "\">Logg ut</a></li>\n";
$result .= "\n\t</ul>\n";
} else {
$result .= "\t<a id=\"login\" href=\"" . htmlspecialchars($as->getLoginURL()) . "\">${svg}Logg inn</a>\n";
$result .= "\t<a id=\"login\" href=\"" . htmlspecialchars($as->getLoginURL()) . "\">{$svg}Logg inn</a>\n";
}
$result .= "\n\t<a href=\"#menu\" id=\"menu_toggle\" aria-hidden=\"true\"><big>&#9776;&nbsp;</big>MENU</a>\n";

12
package.nix Normal file

@@ -0,0 +1,12 @@
{ lib, php }:
php.buildComposerProject (finalAttrs: {
pname = "pvv-nettsiden";
version = "1.0.0";
patchPhase = ''ls -la'';
src = ./.; # TODO: Use builtins.filterSource or similar to clean the source dir
vendorHash = "sha256-APKvVTr7AeCfA1WAzvh6Ex5l8f4Oy46eUoM80vCWMgk=";
})

@@ -32,7 +32,7 @@ class UserManager{
}
public function addGroup($uname, $group){
$userFlags = $this->getUsergroups();
$userFlags = $this->getUsergroups($uname);
if($userFlags){
$newFlags = ($group | $userFlags);
@@ -41,7 +41,7 @@ class UserManager{
}
public function removeGroup($uname, $group){
$userFlags = $this->getUsergroups();
$userFlags = $this->getUsergroups($uname);
if($userFlags){
$newFlags = ($userFlags & (~ $group));
@@ -131,4 +131,4 @@ class UserManager{
return $users;
}
}
}

@@ -8,20 +8,25 @@ use \DateInterval;
class BrettspillActivity implements Activity {
public function nextDate(DateTimeImmutable $date) {
if ($date->format('H') > 20 || $date->format('H') == 19 && $date->format('i') > 30)
return $this->nextDate($date->add(new DateInterval('P1D'))->setTime(19, 30, 0));
$date = $date->setTime(19, 30, 0);
if ($date->format('N') != 4)
if ($date->format('H') > 17 || $date->format('H') == 16 && $date->format('i') > 15)
return $this->nextDate($date->add(new DateInterval('P1D'))->setTime(16, 15, 0));
$date = $date->setTime(16, 15, 0);
if ($date->format('N') != 7)
return $this->nextDate($date->add(new DateInterval('P1D')));
if ($date->format('W') % 2 - 1)
return $this->nextDate($date->add(new DateInterval('P7D')));
return $date;
}
public function prevDate(DateTimeImmutable $date) {
if ($date->format('H') < 19 || $date->format('H') == 20 && $date->format('i') < 30)
return $this->prevDate($date->sub(new DateInterval('P1D'))->setTime(19, 30, 0));
$date = $date->setTime(19, 30, 0);
if ($date->format('N') != 4)
if ($date->format('H') < 16 || $date->format('H') == 17 && $date->format('i') < 15)
return $this->prevDate($date->sub(new DateInterval('P1D'))->setTime(16, 15, 0));
$date = $date->setTime(16, 15, 0);
if ($date->format('N') != 7)
return $this->prevDate($date->sub(new DateInterval('P1D')));
if ($date->format('W') % 2 - 1)
return $this->prevDate($date->sub(new DateInterval('P7D')));
return $date;
}

@@ -16,11 +16,11 @@ class BrettspillEvent extends Event {
}
public function getLocation() /* : Location */ {
return "Koserommet";
return "Programvareverkstedet";
}
public function getOrganiser() /* : User */ {
return "Robert Maikher";
return "Programvareverkstedet";
}
public function getURL() /* : string */ {
@@ -33,8 +33,8 @@ class BrettspillEvent extends Event {
public function getDescription() {
return [
'Er du en hardcore brettspillentusiast eller en nybegynner som har så vidt spilt ludo?'.
'Da er vår brettspillkveld noe for deg!' .
'Er du en hardcore brettspillentusiast eller en nybegynner som har så vidt spilt ludo? '.
'Da er vår brettspillkveld noe for deg! ' .
'Vi tar ut et par spill fra vårt samling of spiller så mye vi orker. Kom innom!',
'',
'## Vår samling',

@@ -11,8 +11,10 @@ class DriftkveldActivity implements Activity {
if ($date->format('H') > 18 || $date->format('H') == 17 && $date->format('i') > 30)
return $this->nextDate($date->add(new DateInterval('P1D'))->setTime(18, 15, 0));
$date = $date->setTime(18, 15, 0);
if ($date->format('N') != 2)
if ($date->format('N') != 6)
return $this->nextDate($date->add(new DateInterval('P1D')));
if ($date->format('W') % 2 - 1)
return $this->nextDate($date->add(new DateInterval('P7D')));
return $date;
}
@@ -20,8 +22,10 @@ class DriftkveldActivity implements Activity {
if ($date->format('H') < 17 || $date->format('H') == 18 && $date->format('i') < 30)
return $this->prevDate($date->sub(new DateInterval('P1D'))->setTime(18, 15, 0));
$date = $date->setTime(18, 15, 0);
if ($date->format('N') != 2)
if ($date->format('N') != 6)
return $this->prevDate($date->sub(new DateInterval('P1D')));
if ($date->format('W') % 2 - 1)
return $this->prevDate($date->sub(new DateInterval('P7D')));
return $date;
}

@@ -24,7 +24,7 @@ class DriftkveldEvent extends Event {
}
public function getURL() /* : string */ {
return '/drift/';
return '/driftkveld/';
}
public function getImageURL() {
@@ -37,7 +37,7 @@ class DriftkveldEvent extends Event {
'Vil du være kul kis TM?',
'Kom på driftkveld!',
'',
'Vi møtes en gang i uka for å ta unna driftarbeid og drikke kaffe.',
'Vi møtes annenhver uke for å ta unna driftarbeid og drikke kaffe.',
'Alle PVVere er velkommene, enten de er erfarne driftere eller helt utenforstående!'
];
}

@@ -0,0 +1,40 @@
<?php //declare(strict_types=1);
namespace pvv\side\social;
use \pvv\side\Activity;
use \DateTimeImmutable;
use \DateInterval;
class HackekveldActivity implements Activity {
public function nextDate(DateTimeImmutable $date) {
if ($date->format('H') > 18 || $date->format('H') == 17 && $date->format('i') > 30)
return $this->nextDate($date->add(new DateInterval('P1D'))->setTime(18, 15, 0));
$date = $date->setTime(16, 15, 0);
if ($date->format('N') != 6)
return $this->nextDate($date->add(new DateInterval('P1D')));
if ($date->format('W') % 2)
return $this->nextDate($date->add(new DateInterval('P7D')));
return $date;
}
public function prevDate(DateTimeImmutable $date) {
if ($date->format('H') < 17 || $date->format('H') == 18 && $date->format('i') < 30)
return $this->prevDate($date->sub(new DateInterval('P1D'))->setTime(18, 15, 0));
$date = $date->setTime(18, 15, 0);
if ($date->format('N') != 6)
return $this->prevDate($date->sub(new DateInterval('P1D')));
if ($date->format('W') % 2)
return $this->prevDate($date->sub(new DateInterval('P7D')));
return $date;
}
public function getNextEventFrom(DateTimeImmutable $date) /* : Event */ {
return new HackekveldEvent($this->nextDate($date));
}
public function getPreviousEventFrom(DateTimeImmutable $date) /* : Event */ {
return new HackekveldEvent($this->prevDate($date));
}
}

@@ -0,0 +1,45 @@
<?php //declare(strict_types=1);
namespace pvv\side\social;
use \pvv\side\Event;
use \DateInterval;
class HackekveldEvent extends Event {
public function getStop() {
return $this->getStart()->add(new DateInterval('PT4H1800S'));
}
public function getName() /* : string */ {
return "Hackekveld";
}
public function getLocation() /* : Location */ {
return "Terminalrommet / Discord / IRC";
}
public function getOrganiser() /* : User */ {
return "PVV";
}
public function getURL() /* : string */ {
return '#';
}
public function getImageURL() {
return '/pvv-logo.png';
}
public function getDescription() {
return [
'Mange PVV-medlemmer liker å programmere.',
'Hvis du også liker å programmere, så bli med! Her kan du jobbe med dine egne prosjekter eller starte noe med andre nerder her på huset. Vi møtes for en hyggelig prat, mye god programmering og delsponset pizza.'
];
}
public function getColor() {
return "#35a";
}
}

@@ -0,0 +1,31 @@
<?xml version="1.0"?>
<clientConfig version="1.1">
<emailProvider id="pvv.ntnu.no">
<domain>pvv.ntnu.no</domain>
<domain>pvv.org</domain>
<displayName>Programvareverkstedet</displayName>
<incomingServer type="imap">
<hostname>imap.pvv.ntnu.no</hostname>
<port>993</port>
<socketType>SSL</socketType>
<username>%EMAILLOCALPART%</username>
<authentication>password-cleartext</authentication>
</incomingServer>
<outgoingServer type="smtp">
<hostname>smtp.pvv.ntnu.no</hostname>
<port>587</port>
<socketType>STARTTLS</socketType>
<username>%EMAILLOCALPART%</username>
<authentication>password-cleartext</authentication>
<useGlobalPreferredServer>true</useGlobalPreferredServer>
</outgoingServer>
<documentation url="https://www.pvv.ntnu.no/pvv/Drift/Mail/IMAP_POP3">
<descr lang="en">Setup programvareverkstedet email user with IMAP or POP3</descr>
<descr lang="nb">Sett opp programvareverkstedet email bruker med IMAP eller POP3</descr>
</documentation>
</emailProvider>
</clientConfig>

@@ -1,154 +1,157 @@
header.landing {
display:block;
margin: 0;
margin-top: 3em;
padding: 3vh 15vw;
width: 70vw;
background-color: #002244;
color: #fff;
display: block;
margin: 0;
margin-top: 3em;
padding: 3vh 15vw;
width: 70vw;
background-color: #002244;
color: #fff;
}
header.landing .logo {
display: block;
width: 24vh;
height: 24vh;
margin: auto;
display: block;
width: 24vh;
height: 24vh;
margin: auto;
}
main {
margin-top: 0;
margin-top: 0;
}
.info {
text-align: center;
width: 100%;
padding: 0;
margin: 0;
text-align: center;
width: 100%;
padding: 0;
margin: 0;
overflow-y: hidden;
overflow-y: hidden;
}
.essentials {
width: 100%;
margin: 1em 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
justify-content: center;
width: 100%;
margin: 1em 0;
padding: 0;
list-style: none;
display: flex;
align-items: center;
justify-content: center;
}
.essentials li {
display: inline-block;
display: inline-block;
}
.essentials a {
margin: 0 2em;
height: 100%;
margin: 0 2em;
height: 100%;
}
.essentials .focus {
padding: 0.8em;
font-size: 1.2em;
padding: 0.8em;
font-size: 1.2em;
}
img.float-right {
float: right;
max-width: 12em;
max-height: 12em;
vertical-align: baseline;
float: right;
max-width: 12em;
max-height: 12em;
vertical-align: baseline;
}
.calendar-events {
padding: 0;
margin-bottom: 1.5em;
list-style: none;
padding: 0;
margin-bottom: 1.5em;
list-style: none;
}
.calendar-events ul li :not(.date):not(.time) {
display: inline-block;
width: calc(100% - 7em);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
display: inline-block;
width: calc(100% - 7em);
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.calendar-events ul .date {
color: rgba(0,0,0,.5);
font-size: 0.8em;
margin-top: .2em;
color: rgba(0, 0, 0, 0.5);
font-size: 0.8em;
margin-top: 0.2em;
}
.calendar-events > li > p {
border-bottom: .1em dotted rgba(0,0,0,.2);
border-bottom: 0.1em dotted rgba(0, 0, 0, 0.2);
}
.calendar-events ul {
list-style: none;
padding: 0;
list-style: none;
padding: 0;
}
.calendar-events a, #ticker a {
text-decoration: none;
font-weight: bold;
color: black;
.calendar-events a,
#ticker a {
text-decoration: none;
font-weight: bold;
color: black;
}
.calendar-events a:hover, #ticker a:hover {
text-decoration: underline;
.calendar-events a:hover,
#ticker a:hover {
text-decoration: underline;
}
.calendar-events ul .time {
color: rgba(0,0,0,.5);
float: right;
color: rgba(0, 0, 0, 0.5);
float: right;
}
.calendar-events ul .icon, .calendar-events ul .date {
float: right;
margin-right: .5em;
.calendar-events ul .icon,
.calendar-events ul .date {
float: right;
margin-right: 0.5em;
}
main.contentsplit {
padding-top: 1em;
padding-top: 1em;
}
.contentsplit {
display: grid;
grid-template-columns: 2.5fr 2fr;
display: grid;
grid-template-columns: 2.5fr 2fr;
}
.gridr {
border-left: 0;
border-left: 0;
}
@media screen and (max-width: 50rem) {
.essentials {
flex-direction: column;
}
.essentials {
flex-direction: column;
}
.essentials a {
margin: .2em 0;
}
.essentials a {
margin: 0.2em 0;
}
}
@media screen and (max-width: 65rem) {
.contentsplit {
display: block;
}
.contentsplit {
display: block;
}
.gridr {
height: auto;
padding: 0;
margin-left: 0;
margin-bottom: 3em;
}
.gridr {
height: auto;
padding: 0;
margin-left: 0;
margin-bottom: 3em;
}
.gridr br {
margin: 0;
height: 0px;
}
.gridr br {
margin: 0;
height: 0px;
}
.gridl {
margin-top: 0;
padding: 0;
}
.gridl {
margin-top: 0;
padding: 0;
}
}

93
www/css/services.css Normal file

@@ -0,0 +1,93 @@
main {
margin: 0px !important;
padding: 0px !important;
width: 100vw;
}
.serviceWrapper {
width: 80%;
display: grid;
grid-template-columns: 1fr 1fr;
grid-gap: 1em;
margin: auto auto;
margin-top: 4em;
}
.categoryContainer {
border: 4px solid #002244;
border-radius: 5px;
box-shadow : 0 0 20px #002244;
margin-bottom: 20px;
}
.categoryLabel {
background-color: #002244;
color: white;
padding-left: 10px;
font-family: monospace;
font-size: 24px;
}
.service {
border: 2px solid #002244;
border-radius: 5px;
padding: 10px;
margin: 10px;
display: flex;
flex-direction: row;
}
.serviceContent {
flex-grow: 1;
}
.serviceTitle {
margin: 0.2em !important;
}
.serviceDescription {
margin-top: 0px !important;
}
.serviceDescription::before {
content: " - ";
font-size: 18px;
display: inline;
}
.serviceLink {
width: 70%;
padding-bottom: 5px;
border-radius: 5px;
border: 2px solid #002244;
padding: 7px;
margin-top: 4px;
}
.serviceLink > a {
margin-bottom: 10px;
word-break: break-word;
}
.serviceImage {
flex-shrink: 1;
width: 100px;
height: 100px;
margin: auto auto;
}
@media (max-width: 800px) {
.serviceWrapper {
grid-template-columns: 1fr;
}
.categoryContainer {
width: 100%;
}
}

@@ -74,7 +74,7 @@ function handleSetState() {
die();
}
$door->createEvent((int)($event->time), (bool)($event->isDoorOpen));
$door->createEvent((int)($event->time), $event->isDoorOpen ? 1 : 0);
echo '{"status": "OK"}';
}
@@ -90,4 +90,4 @@ function getChanges($items) {
}
return $res;
}
}

@@ -14,7 +14,7 @@ use \pvv\side\Agenda;
<meta name="theme-color" content="#024" />
<title>Drifterverkstedet</title>
<header>Sosial&shy;verk&shy;stedet</header>
<header>Drift&shy;verk&shy;stedet</header>
<main>

@@ -1,14 +1,23 @@
#!/usr/bin/env bash
outfolder="bilder/pvv-photos"
folders=$(ssh pvv@microbel.pvv.ntnu.no -i /home/pvv/c/pvv/.ssh/photofetcher 'find /home/pvv -maxdepth 3 -name "pvv-photos" 2>/dev/null')
echo "Fetching user list"
# Note: `~pvv/.ssh/authorized_keys` forces the command as such
folders="$(ssh pvv@microbel.pvv.ntnu.no -i /home/pvv/c/pvv/.ssh/photofetcher 'cat /etc/passwd' | while read line; do test `echo "$line" | cut -d: -f 3` -gt 1000 && echo "$(echo $line | cut -d: -f 6)/pvv-photos" ; done)"
unamefile="usernames.txt"
> $unamefile # Empty the file
for imgfolder in $folders; do
user=$(echo $imgfolder | cut -d "/" -f5)
if ! test -d "$imgfolder"; then continue; fi
echo found $imgfolder
user="$(echo $imgfolder | cut -d "/" -f5)"
realname="$(getent passwd $user | cut -d ':' -f 5)"
echo "$user:$realname" >> $unamefile
echo "$user:$realname" >> "$unamefile"
destination="$outfolder/$user"
mkdir -p $destination
mkdir -p "$destination"
rsync -rtvz --delete "$imgfolder/" "$destination" # Copy and keep timestamps
done
echo
done

@@ -1,7 +0,0 @@
#! /usr/bin/env bash
#fetchPics.sh 1> /dev/null
cd /usr/local/www/www_pvv_ntnu_no/www/galleri/
./fetchPics.sh 1>/dev/null

@@ -5,20 +5,20 @@ require_once dirname(dirname(__DIR__)) . implode(DIRECTORY_SEPARATOR, ['', 'inc'
$pdo = new \PDO($dbDsn, $dbUser, $dbPass);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
#$userManager = new \pvv\admin\UserManager($pdo);
#
#$as = new SimpleSAML_Auth_Simple('default-sp');
#$as->requireAuth();
#$attrs = $as->getAttributes();
#$loginname = $attrs['uid'][0];
#
#if(!$loginname) {
# header('Content-Type: text/plain', true, 403);
# echo "Du må være logget inn for å se bildegalleriet.\r\n";
# exit();
#}
#
#
$userManager = new \pvv\admin\UserManager($pdo);
$as = new SimpleSAML_Auth_Simple('default-sp');
$as->requireAuth();
$attrs = $as->getAttributes();
$loginname = $attrs['uid'][0];
if(!$loginname) {
header('Content-Type: text/plain', true, 403);
echo "Du må være logget inn for å se bildegalleriet.\r\n";
exit();
}
$unamefile = __DIR__ . '/usernames.txt';
$relativePath = "/bilder/pvv-photos/";
$allowedExtensions = ['jpg', 'jpeg', 'png', 'gif', 'bmp', 'svg', 'webp'];
@@ -38,7 +38,7 @@ function getDirContents($dir, &$results = array()) {
}
//Check if the file is an image
$ext = pathinfo($path, PATHINFO_EXTENSION);
$ext = strtolower(pathinfo($path, PATHINFO_EXTENSION));
if (in_array($ext, $GLOBALS["allowedExtensions"])) {
$results[] = $cleanPath;
}
@@ -78,7 +78,6 @@ $imageTemplate = '
<link rel="stylesheet" href="../css/normalize.css">
<link rel="stylesheet" href="../css/style.css">
<link rel="stylesheet" href="../css/gallery.css">
<link rel="stylesheet" href="../css/bulma.min.css">
<meta name="theme-color" content="#024" />
<title>Fotoverkstedet</title>
</head>
@@ -112,6 +111,11 @@ $imageTemplate = '
];
echo strtr($imageTemplate, $vars);
}
if (count($images) == 0) {
echo "<h3 class='no-images'>Det er dessverre ingen bilder å vise.</h3>";
}
?>
</main>
<div id="modal" class="modal">

@@ -40,11 +40,10 @@ $doorTime = date("H:i", $doorEntry->time);
</nav>
<header class="landing">
<div id="imageSlideshow">
<div id="imageSlideshow">
<?php include("galleri/slideshow.php"); ?>
<script src="js/slideshow.js"></script>
</div>
<div class="info">
<h2>Velkommen til Programvare&shy;verkstedet</h2>
<p>Programvareverkstedet (PVV) er en studentorganisasjon ved NTNU som vil skape et miljø for datainteresserte personer tilknyttet universitetet.</p>

@@ -9,7 +9,7 @@ require_once dirname(dirname(__DIR__)) . implode(DIRECTORY_SEPARATOR, ['', 'inc'
<link rel="stylesheet" href="../css/normalize.css">
<link rel="stylesheet" href="../css/style.css">
<link rel="stylesheet" href="../css/events.css">
<meta name="theme-color" content="#024" />
<meta name="theme-color" content="#024" >
<title>Kommunikasjonsverkstedet</title>
<header>Kommunikasjons&shy;verk&shy;stedet</header>
@@ -22,22 +22,32 @@ require_once dirname(dirname(__DIR__)) . implode(DIRECTORY_SEPARATOR, ['', 'inc'
</nav>
<main>
<h2>Kommunikasjon<br><img style="width: 8em" src="kontakt.jpg"></img></h2>
<h2>
Kontaktinformasjon
<a href="https://en.wikipedia.org/wiki/IP_over_Avian_Carriers">
<img style="width: 8em" src="kontakt.jpg">
</a>
</h2>
<p> Det er flere ulike måter å kommunisere med PVV og deres medlemmer på.
<p>
Vi kan kontaktes på følgende e-postadresser:
<ul>
<li><a href="mailto:pvv@pvv.ntnu.no">pvv@pvv.ntnu.no</a> for hendvendelser til styret</li>
<li><a href="mailto:drift@pvv.ntnu.no">drift@pvv.ntnu.no</a> for hendvendelser anngående våre datasystemer</li>
</ul>
</p>
<p> Du kan registrere deg på våre <a href="http://list.pvv.org/mailman/listinfo/aktive">Aktive epostlister</a> for å få informasjon om de kommende aktivitetene våre.
<p>Det er også mulig å ta kontakt med oss ved å møte opp <a href="https://link.mazemap.com/JqgWGSnh">på våre lokaler i oppredning/gruvedrift</a>.</p>
<p> Kontaktinformasjonen til Styret og Drift funner du på vår <a href="../pvv/Kontaktinformasjon">Wiki</a>
<h2>Kommunikasjonskanaler</h2>
<p> Vi har en IRC-kanal på <a href="http://webchat.ircnet.net/">IRCnet</a> kalt #pvv.
<p>Vi har en <a href="http://list.pvv.org/mailman/listinfo/aktive">e-postliste for aktive medlemmer</a>. All offisiell informasjon blir sendt på denne listen, og alle arrengementer blir også annonsert her.</p>
<p> Vi har også en Discord-kanal. Denne kanalen er satt opp slik at man i Discord-kanalen ser hva som skrives i IRC-kanalen, og vice versa. For å bli med i Discord-kanalen, <a href="https://discord.gg/8VTBr6Q">klikk her</a>.
<!--
<i>(Denne broen for øyeblikket ute av drift)</i>
-->
<p>Vi har en <a target="_blank" href="https://matrix.to/#/#pvv:pvv.ntnu.no">Matrix-server</a> for chat, memes, og all annen kommunikasjon. Den er bridget med IRC-kanalen og Discord-guilden vår. Hvis du er medlem kan du bruke vår <a href="https://chat.pvv.ntnu.no">self-hosted web client</a>.</p>
<p>Vi har en IRC-kanal på <a href="http://webchat.ircnet.net/">IRCnet</a> kalt #pvv.</p>
<p> Det er også mulig å ta i bruk analog kontakt ved å møte opp <a href="https://bit.ly/31P6yr5">på våre lokaler i oppredning/gruvedrift</a>.
<p>Vi har en <a target="_blank" href="https://discord.gg/8VTBr6Q">Discord-guild</a> for de som foretrekker Discord over Matrix. </p>
</main>
</body>

@@ -47,7 +47,7 @@ p {hyphens: auto;}
}
</style>
<div class="iframe-container" style="max-width: 100em;">
<iframe class="responsive-iframe" src="https://www.youtube.com/embed/l-iEkaQNQdk" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe>
<iframe class="responsive-iframe" src="https://www.youtube.com/embed/Uy6HAvMdeuA" title="YouTube video player" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen ></iframe>
</div>
</article>

18
www/robots.txt Normal file

@@ -0,0 +1,18 @@
# This file set up by fredj according to proposed Standard of Robot
# Exclusion at http://web.nexor.co.uk/mak/doc/robots/norobots.html
#
# Currently: allow all robots.
# (An empty 'Disallow' line, looking like this:)
# User-agent: * # Means: All robots.
# Disallow: # Means: Disallow nothing.
User-agent: *
Disallow: /usage
Disallow: /news_archive
Disallow: /cgi
Disallow: /finger
Disallow: /cgi-bin
Disallow: /~pallo/usage/
Disallow: /~pallo/historic/
Disallow: /~meldahl/
Disallow: /w/index.php?

Binary file not shown.

After

(image error) Size: 52 KiB

Binary file not shown.

After

(image error) Size: 4.6 KiB

BIN
www/tjenester/img/email.png Normal file

Binary file not shown.

After

(image error) Size: 42 KiB

BIN
www/tjenester/img/esxi.png Normal file

Binary file not shown.

After

(image error) Size: 2.3 KiB

Binary file not shown.

After

(image error) Size: 22 KiB

Binary file not shown.

After

(image error) Size: 6.9 KiB

BIN
www/tjenester/img/gogs.png Normal file

Binary file not shown.

After

(image error) Size: 40 KiB

BIN
www/tjenester/img/irc.png Normal file

Binary file not shown.

After

(image error) Size: 14 KiB

Binary file not shown.

After

(image error) Size: 58 KiB

BIN
www/tjenester/img/php.png Normal file

Binary file not shown.

After

(image error) Size: 31 KiB

Binary file not shown.

After

(image error) Size: 47 KiB

BIN
www/tjenester/img/rss.png Normal file

Binary file not shown.

After

(image error) Size: 117 KiB

BIN
www/tjenester/img/trac.png Normal file

Binary file not shown.

After

(image error) Size: 11 KiB

209
www/tjenester/index.php Normal file

@@ -0,0 +1,209 @@
<?php namespace pvv\side;
require_once dirname(dirname(__DIR__)) . implode(DIRECTORY_SEPARATOR, ['', 'inc', 'include.php']);
?>
<!DOCTYPE html>
<html lang="no">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="/css/normalize.css">
<link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/services.css">
<meta name="theme-color" content="#024" />
<title>Tjenesteverkstedet</title>
<header>Tjenesteverkstedet</header>
<body>
<nav>
<?= navbar(1, 'tjenester'); ?>
<?= loginbar($sp, $pdo); ?>
</nav>
<main>
<div class="serviceWrapper">
<div class="categoryContainer">
<div class="categoryLabel">Versjonskontroll og utvikling</div>
<div class="categoryContent">
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">GitHub</h2>
<p class="serviceDescription">Våre offentlige kodebrønner, åpent for verden!</p>
<div class="serviceLink"><a href="https://github.com/Programvareverkstedet/" target="_blank">Gå til GitHub</a></div>
</div>
<img class="serviceImage" src="img/github.png" alt="GitHub-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Gogs</h2>
<p class="serviceDescription">Vår interne git-tjener, åpen for alle medlemmer</p>
<div class="serviceLink"><a href="https://git.pvv.ntnu.no" target="_blank">Gå til git.pvv.ntnu.no</a></div>
</div>
<img class="serviceImage" src="img/gogs.png" alt="Gogs-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Dev og Trac</h2>
<p class="serviceDescription">Trac er vårt gamle prosjektsystem. Her kan du lage og dele prosjekter om du er for hipster for github.</p>
<div class="serviceLink"><a href="https://dev.pvv.ntnu.no/projects/pvv-dev/" target="_blank">Gå til dev.pvv.ntnu.no</a></div>
</div>
<img class="serviceImage" src="img/trac.png" alt="Trac-logo">
</div>
</div>
</div>
<div class="categoryContainer">
<div class="categoryLabel">Kommunikasjon</div>
<div class="categoryContent">
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Matrix via Element</h2>
<p class="serviceDescription">Åpen kommunikasjonsprotokoll som støtter ende-til-ende-kryptering og utallige kule funksjoner. Vårt space er bridget sammen med Discord, så du får alle de samme meldingene. <b>#pvv:pvv.ntnu.no</b></p>
<div class="serviceLink">
<a href="https://chat.pvv.ntnu.no" target="_blank">Gå til chat.pvv.ntnu.no(medlem)</a>
</div>
<div class="serviceLink">
<a href="https://matrix.to/#/#pvv:pvv.ntnu.no" target="_blank">Gå til #pvv:pvv.ntnu.no(offentlig)</a>
</div>
</div>
<img class="serviceImage" src="img/element.png" alt="Element-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Discord</h2>
<p class="serviceDescription">Vår hovedkanal, her finner du alt fra ofisielle announcements til memes og driftsdiskusjoner.</p>
<div class="serviceLink"><a href="https://discord.gg/WpaHGV8K" target="_blank">Gå til Discord</a></div>
</div>
<img class="serviceImage" src="img/discord.png" alt="Discord-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Epost</h2>
<p class="serviceDescription">Som PVV-medlem får du din egen @pvv.ntnu.no-adresse, som kan brukes med alle vanlige epostprotokoller.</p>
<div class="serviceLink">
<a href="https://www.pvv.ntnu.no/mail/" target="_blank">Gå til Webmail</a>
</div>
<div class="serviceLink">
<a href="https://www.pvv.ntnu.no/pvv/Drift/Mail/IMAP_POP3/" target="_blank">IMAP/POP/SMTP-innstillinger</a>
</div>
</div>
<img class="serviceImage" src="img/email.png" alt="Epost-ikon">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">IRC</h2>
<p class="serviceDescription">Hvis Discord er for proprietært og Matrix er for hypermoderne er kanskje IRC for deg. Vi har en kanal på IRCNet, <b>#pvv</b>.</p>
<div class="serviceLink"><a href="irc://irc.pvv.ntnu.no/pvv" target="_blank">Koble til med IRC</a></div>
</div>
<img class="serviceImage" src="img/irc.png" alt="IRC-ikon">
</div>
</div>
</div>
<div class="categoryContainer">
<div class="categoryLabel">Hosting</div>
<div class="categoryContent">
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Brukernettsider</h2>
<p class="serviceDescription">Alle brukere får automatisk en egen side for html og php. Denne er offentlig på pvv.ntnu.no/~brukernavn.</p>
<div class="serviceLink"><a href="https://www.pvv.ntnu.no/pvv/Hjemmesider" target="_blank">Gå til dokumentasjon på wiki</a></div>
</div>
<img class="serviceImage" src="img/php.png" alt="En elephpant">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">PVV-siden</h2>
<p class="serviceDescription">Du befinner deg nå på PVV sin offisielle hjemmeside. Den er skrevet i PHP og kjører på en egen server.</p>
<div class="serviceLink"><a href="https://github.com/Programvareverkstedet/nettsiden" target="_blank">Se koden på github</a></div>
</div>
<img class="serviceImage" src="../pvv-logo.png" alt="PVV-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Proxmox @joshua</h2>
<p class="serviceDescription">Joshua er en av våre VM-tjenere, her kan du kjøre enten fulle VM-er eller konteinere. Bare Drift har tilgang på disse tjenerne.</p>
<div class="serviceLink"><a href="https://joshua.pvv.ntnu.no:8006" target="_blank">Gå til joshua.pvv.ntnu.no</a></div>
</div>
<img class="serviceImage" src="img/proxmox.png" alt="Proxmox-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Proxmox @andresbu</h2>
<p class="serviceDescription">Andresbu er en kraftigere VM-tjener, men har fortsatt en del rusk i maskineriet.</p>
<div class="serviceLink"><a href="https://andresbu.pvv.ntnu.no:8006" target="_blank">Gå til andresbu.pvv.ntnu.no</a></div>
</div>
<img class="serviceImage" src="img/proxmox.png" alt="Proxmox-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">ESXI @asgore</h2>
<p class="serviceDescription">Asgore er vår eldste og største VM-tjener, og kjører ESXI.</p>
<div class="serviceLink"><a href="https://asgore.pvv.ntnu.no" target="_blank">Gå til asgore.pvv.ntnu.no</a></div>
</div>
<img class="serviceImage" src="img/esxi.png" alt="ESXI-logo">
</div>
</div>
</div>
<div class="categoryContainer">
<div class="categoryLabel">Underholdning</div>
<div class="categoryContent">
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Minecraft</h2>
<p class="serviceDescription">Vi har en egen Minecraft-server <b>for medlemmer</b>, som du kan koble til med IP-adressen <b>minecraft.pvv.ntnu.no</b>. Spør om whitelist på matrix/discord.</p>
<div class="serviceLink"><a href="https://isvegg.pvv.ntnu.no/kart/" target="_blank">Gå til verdenskartet vårt</a></div>
</div>
<img class="serviceImage" src="img/minecraft.png" alt="Minecraft-logo">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">MiniFlux RSS reader</h2>
<p class="serviceDescription">Trenger du en cross-platform RSS/Atom-leser for å følge med på omverdenen som det er 1990? </p>
<div class="serviceLink"><a href="https://feeds.pvv.ntnu.no" target="_blank">Gå til MiniFlux</a></div>
</div>
<img class="serviceImage" src="img/rss.png" alt="RSS-Ikon">
</div>
<div class="service">
<div class="serviceContent">
<h2 class="serviceTitle">Bildegalleri</h2>
<p class="serviceDescription">PVV har et felles bildegalleri, der alle kan legge relevante bilder, som automatisk blir inkludert på nettsiden.</p>
<div class="serviceLink">
<a href="https://www.pvv.ntnu.no/galleri/" target="_blank">Se galleriet</a>
</div>
<div class="serviceLink">
<a href="https://www.pvv.ntnu.no/pvv/Bildedeling" target="_blank">Opplasting</a>
</div>
</div>
<img class="serviceImage" src="img/gallery.png" alt="RSS-Ikon">
</div>
<!-- Bokhylle /brzeczyszczykiewicz ? -->
</div>
</div>
</div>
</main>
</body>
</html>