4 Commits

13 changed files with 572 additions and 390 deletions

View File

@@ -8,21 +8,51 @@ CREATE TABLE events (
`description` TEXT `description` TEXT
); );
CREATE TABLE projects ( CREATE TABLE project_group (
`id` INTEGER PRIMARY KEY AUTO_INCREMENT, `id` INTEGER PRIMARY KEY AUTO_INCREMENT,
`name` TEXT, `title` TEXT NOT NULL,
`description` TEXT, `description_en` TEXT NOT NULL,
`active` BOOLEAN DEFAULT TRUE `description_no` TEXT NOT NULL,
`gitea_link` TEXT NOT NULL,
`wiki_link` TEXT
); );
CREATE TABLE projectmembers ( INSERT INTO
`projectid` INTEGER, project_group (title, description_en, description_no, gitea_link, wiki_link)
`name` TEXT, VALUES
`uname` TEXT, (
`mail` TEXT, 'Projects',
`role` TEXT, 'Projects developed by members of PVV.',
`lead` BOOLEAN DEFAULT FALSE, 'Prosjekter utviklet av medlemmer i PVV.',
`owner` BOOLEAN DEFAULT FALSE 'https://git.pvv.ntnu.no/Projects',
'https://wiki.pvv.ntnu.no/wiki/Programvareutvikling'
);
CREATE TABLE project (
`id` INTEGER PRIMARY KEY AUTO_INCREMENT,
`group_id` INTEGER NOT NULL REFERENCES project_group (id) DEFAULT 1,
`title` TEXT NOT NULL,
`description_en` TEXT NOT NULL,
`description_no` TEXT NOT NULL,
`gitea_link` TEXT,
`issue_board_link` TEXT,
`wiki_link` TEXT,
`languages` TEXT,
`technologies` TEXT,
`keywords` TEXT,
`license` TEXT,
`logo_url` TEXT,
FOREIGN KEY (group_id) REFERENCES project_group (id) ON DELETE SET DEFAULT
);
CREATE TABLE project_maintainer (
`uname` TEXT NOT NULL,
`project_id` INTEGER NOT NULL,
`name` TEXT NOT NULL,
`email` TEXT,
`is_owner` BOOLEAN DEFAULT FALSE,
PRIMARY KEY (uname, project_id),
FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE
); );
CREATE TABLE users (`uname` TEXT, `groups` INT DEFAULT 0); CREATE TABLE users (`uname` TEXT, `groups` INT DEFAULT 0);

View File

@@ -8,23 +8,57 @@ CREATE TABLE "events" (
"description" TEXT "description" TEXT
); );
CREATE TABLE "projects" ( -- PROJECTS
CREATE TABLE "project_group" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT, "id" INTEGER PRIMARY KEY AUTOINCREMENT,
"name" TEXT, "title" TEXT NOT NULL,
"description" TEXT, "description_en" TEXT NOT NULL,
"active" BOOLEAN DEFAULT TRUE "description_no" TEXT NOT NULL,
"gitea_link" TEXT NOT NULL,
"wiki_link" TEXT
); );
CREATE TABLE "projectmembers" ( INSERT INTO
"projectid" INTEGER, project_group (title, description_en, description_no, gitea_link, wiki_link)
"name" TEXT, VALUES
"uname" TEXT, (
"mail" TEXT, 'Projects',
"role" TEXT, 'Projects developed by members of PVV.',
"lead" BOOLEAN DEFAULT FALSE, 'Prosjekter utviklet av medlemmer i PVV.',
"owner" BOOLEAN DEFAULT FALSE 'https://git.pvv.ntnu.no/Projects',
'https://wiki.pvv.ntnu.no/wiki/Programvareutvikling'
); );
CREATE TABLE "project" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT,
"group_id" INTEGER NOT NULL DEFAULT 1,
"title" TEXT NOT NULL,
"description_en" TEXT NOT NULL,
"description_no" TEXT NOT NULL,
"gitea_link" TEXT,
"issue_board_link" TEXT,
"wiki_link" TEXT,
"languages" TEXT,
"technologies" TEXT,
"keywords" TEXT,
"license" TEXT,
"logo_url" TEXT,
FOREIGN KEY (group_id) REFERENCES project_group (id) ON DELETE SET DEFAULT
);
CREATE TABLE "project_maintainer" (
"uname" TEXT NOT NULL,
"project_id" INTEGER NOT NULL,
"name" TEXT NOT NULL,
"email" TEXT,
"is_owner" BOOLEAN DEFAULT FALSE,
PRIMARY KEY (uname, project_id),
FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE
);
--
CREATE TABLE "users" ("uname" TEXT, "groups" INT DEFAULT 0); CREATE TABLE "users" ("uname" TEXT, "groups" INT DEFAULT 0);
CREATE TABLE "motd" ( CREATE TABLE "motd" (

View File

@@ -29,7 +29,7 @@ You should now be able to access the site at [http://localhost:1080](http://loca
Sometimes it is useful to completely reset the state of the project, deleting the data, redownloading dependencies, etc. You can do this by running `./scripts/reset.sh`. Be careful, as this will delete all data in the database! Sometimes it is useful to completely reset the state of the project, deleting the data, redownloading dependencies, etc. You can do this by running `./scripts/reset.sh`. Be careful, as this will delete all data in the database!
> [!WARNING] > [!WARN]
> Even when resetting the project with the reset script, there are some situation where you need to clear your cookies or your browser cache to get a clean state. > Even when resetting the project with the reset script, there are some situation where you need to clear your cookies or your browser cache to get a clean state.
> How to do this varies between browsers, so please refer to your browser's documentation for instructions. > How to do this varies between browsers, so please refer to your browser's documentation for instructions.

View File

@@ -6,35 +6,120 @@ namespace pvv\side;
class Project { class Project {
private int $id; private int $id;
private string $name; private string $title;
private array $descr; private array $description_en;
private bool $active; private array $description_no;
private ?string $gitea_link;
private ?string $issue_board_link;
private ?string $wiki_link;
private array $programming_languages;
private array $technologies;
private array $keywords;
// NOTE: spdx identifier
private ?string $license;
private ?string $logo_url;
public function __construct( public function __construct(
int $id, int $id,
string $name, string $title,
string $descr, ?string $description_en,
bool $active, ?string $description_no,
?string $gitea_link,
?string $issue_board_link,
?string $wiki_link,
?string $programming_languages,
?string $technologies,
?string $keywords,
?string $license,
?string $logo_url,
) { ) {
$this->id = $id; $this->id = $id;
$this->name = $name; $this->title = $title;
$this->descr = explode("\n", $descr); $this->description_en
$this->active = $active; = $description_en === null || $description_en === ''
? []
: explode("\n", $description_en);
$this->description_no
= $description_no === null || $description_no === ''
? []
: explode("\n", $description_no);
$this->gitea_link = $gitea_link;
$this->issue_board_link = $issue_board_link;
$this->wiki_link = $wiki_link;
$this->programming_languages
= $programming_languages === null || $programming_languages === ''
? []
: explode(',', $programming_languages);
$this->technologies
= $technologies === null || $technologies === ''
? []
: explode(',', $technologies);
$this->keywords
= $keywords === null || $keywords === '' ? [] : explode(',', $keywords);
$this->license = $license;
$this->logo_url = $logo_url;
} }
public function getID(): int { public function getID(): int {
return $this->id; return $this->id;
} }
public function getName(): string { public function getTitle(): string {
return $this->name; return $this->title;
} }
public function getDescription(): array { /**
return $this->descr; * @return string[]
*/
public function getDescriptionEn(): array {
return $this->description_en;
} }
public function getActive(): bool { /**
return $this->active; * @return string[]
*/
public function getDescriptionNo(): array {
return $this->description_no;
}
public function getGiteaLink(): ?string {
return $this->gitea_link;
}
public function getIssueBoardLink(): ?string {
return $this->issue_board_link;
}
public function getWikiLink(): ?string {
return $this->wiki_link;
}
/**
* @return string[]
*/
public function getProgrammingLanguages(): array {
return $this->programming_languages;
}
/**
* @return string[]
*/
public function getTechnologies(): array {
return $this->technologies;
}
/**
* @return string[]
*/
public function getKeywords(): array {
return $this->keywords;
}
public function getLicense(): ?string {
return $this->license;
}
public function getLogoURL(): ?string {
return $this->logo_url;
} }
} }

View File

@@ -11,11 +11,13 @@ class ProjectManager {
$this->pdo = $pdo; $this->pdo = $pdo;
} }
// TODO: groupid
/** /**
* @return Project[] * @return Project[]
*/ */
public function getAll(): array { public function getAll(): array {
$query = 'SELECT * FROM projects ORDER BY id ASC'; $query = 'SELECT * FROM project ORDER BY id ASC';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->execute(); $statement->execute();
@@ -23,9 +25,17 @@ class ProjectManager {
foreach ($statement->fetchAll() as $dbProj) { foreach ($statement->fetchAll() as $dbProj) {
$project = new Project( $project = new Project(
$dbProj['id'], $dbProj['id'],
$dbProj['name'], $dbProj['title'],
$dbProj['description'], $dbProj['description_en'],
(bool) $dbProj['active'], $dbProj['description_no'],
$dbProj['gitea_link'],
$dbProj['issue_board_link'],
$dbProj['wiki_link'],
$dbProj['languages'],
$dbProj['technologies'],
$dbProj['keywords'],
$dbProj['license'],
$dbProj['logo_url']
); );
$projects[] = $project; $projects[] = $project;
} }
@@ -33,8 +43,9 @@ class ProjectManager {
return $projects; return $projects;
} }
// TODO: groupid
public function getByID(int $id): ?Project { public function getByID(int $id): ?Project {
$query = 'SELECT * FROM projects WHERE id=:id LIMIT 1'; $query = 'SELECT * FROM project WHERE id=:id LIMIT 1';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindParam(':id', $id, \PDO::PARAM_INT); $statement->bindParam(':id', $id, \PDO::PARAM_INT);
$statement->execute(); $statement->execute();
@@ -46,17 +57,33 @@ class ProjectManager {
return new Project( return new Project(
$dbProj['id'], $dbProj['id'],
$dbProj['name'], $dbProj['title'],
$dbProj['description'], $dbProj['description_en'],
(bool) $dbProj['active'], $dbProj['description_no'],
$dbProj['gitea_link'],
$dbProj['issue_board_link'],
$dbProj['wiki_link'],
$dbProj['languages'],
$dbProj['technologies'],
$dbProj['keywords'],
$dbProj['license'],
$dbProj['logo_url']
); );
} }
// TODO: groupid
/** /**
* @return Project[] * @return Project[]
*/ */
public function getByOwner(string $uname): array { public function getByOwner(string $uname): array {
$query = 'SELECT projectid FROM projectmembers WHERE uname=:uname'; $query = '
SELECT project.id FROM project
JOIN project_maintainer ON project.id = project_maintainer.project_id
WHERE project_maintainer.uname = :uname
AND project_maintainer.is_owner = TRUE
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindParam(':uname', $uname, \PDO::PARAM_STR); $statement->bindParam(':uname', $uname, \PDO::PARAM_STR);
$statement->execute(); $statement->execute();
@@ -74,9 +101,17 @@ class ProjectManager {
foreach ($statement->fetchAll() as $dbProj) { foreach ($statement->fetchAll() as $dbProj) {
$project = new Project( $project = new Project(
$dbProj['id'], $dbProj['id'],
$dbProj['name'], $dbProj['title'],
$dbProj['description'], $dbProj['description_en'],
(bool) $dbProj['active'], $dbProj['description_no'],
$dbProj['gitea_link'],
$dbProj['issue_board_link'],
$dbProj['wiki_link'],
$dbProj['languages'],
$dbProj['technologies'],
$dbProj['keywords'],
$dbProj['license'],
$dbProj['logo_url']
); );
$projects[] = $project; $projects[] = $project;
} }
@@ -86,47 +121,66 @@ class ProjectManager {
} }
/** /**
* @return array<int,array> * @return {uname:string,name:string,link:string,email:string,is_owner:bool}[]
*/ */
public function getProjectMembers(int $id): array { public function getProjectMembers(int $project_id): array {
$query = 'SELECT * FROM projectmembers WHERE projectid=:id'; $query = '
SELECT
project_maintainer.uname,
project_maintainer.name,
project_maintainer.email,
project_maintainer.is_owner
FROM project_maintainer
WHERE project_maintainer.project_id = :id
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindParam(':id', $id, \PDO::PARAM_STR); $statement->bindParam(':id', $project_id, \PDO::PARAM_STR);
$statement->execute(); $statement->execute();
$members = []; $maintainers = [];
foreach ($statement->fetchAll() as $dbUsr) { foreach ($statement->fetchAll() as $dbUsr) {
$members[] = [ $maintainers[] = [
'name' => $dbUsr['name'],
'uname' => $dbUsr['uname'], 'uname' => $dbUsr['uname'],
'mail' => $dbUsr['mail'], 'name' => $dbUsr['name'],
'role' => $dbUsr['role'], 'email' => $dbUsr['email'],
'lead' => (bool) $dbUsr['lead'], 'is_owner' => (bool)$dbUsr['is_owner'],
'owner' => (bool) $dbUsr['owner'],
]; ];
} }
return $members; return $maintainers;
} }
/** /**
* @return array<string,mixed> * @return array{name:string,uname:string,email:string,is_owner:bool}|null
*/ */
public function getProjectOwner(int $id): array { public function getProjectOwner(int $project_id): ?array {
$query = 'SELECT * FROM projectmembers WHERE (projectid=:id AND owner=1)'; $query = '
SELECT
project_maintainer.name,
project_maintainer.uname,
project_maintainer.email,
project_maintainer.is_owner
FROM project_maintainer
WHERE project_maintainer.project_id = :id
AND project_maintainer.is_owner = TRUE
LIMIT 1
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindParam(':id', $id, \PDO::PARAM_STR); $statement->bindParam(':id', $project_id, \PDO::PARAM_STR);
$statement->execute(); $statement->execute();
$dbOwner = $statement->fetch(); $owner = $statement->fetch();
if (!$owner) {
return null;
}
return [ return [
'name' => $dbOwner['name'], 'name' => $owner['name'],
'uname' => $dbOwner['uname'], 'uname' => $owner['uname'],
'mail' => $dbOwner['mail'], 'email' => $owner['email'],
'role' => $dbOwner['role'], 'is_owner' => (bool)$owner['is_owner'],
'lead' => (bool) $dbOwner['lead'],
'owner' => (bool) $dbOwner['owner'],
]; ];
} }
} }

View File

@@ -39,22 +39,22 @@ class BrettspillEvent extends Event {
'', '',
'## Vår samling', '## Vår samling',
'', '',
'* Dominion\\*', '* Dominion\*',
'* Three cheers for master', '* Three cheers for master',
'* Avalon', '* Avalon',
'* Hanabi', '* Hanabi',
'* Cards aginst humanity\\*', '* Cards aginst humanity\*',
'* Citadels', '* Citadels',
'* Munchkin\\*\\*', '* Munchkin\*\*',
'* Exploding kittens\\*\\*', '* Exploding kittens\*\*',
'* Aye dark overlord', '* Aye dark overlord',
'* Settlers of catan\\*', '* Settlers of catan\*',
'* Risk\\*\\*', '* Risk\*\*',
'* og mange flere...', '* og mange flere...',
'', '',
'\\* Vi har flere ekspansjoner til spillet', '\* Vi har flere ekspansjoner til spillet',
'', '',
'\\*\\* Vi har flere varianter av spillet', '\*\* Vi har flere varianter av spillet',
]; ];
} }

View File

@@ -18,7 +18,7 @@ if (!$userManager->hasGroup($uname, 'prosjekt')) {
$projectID = $_GET['id']; $projectID = $_GET['id'];
$query = 'DELETE FROM projects WHERE id=\'' . $projectID . '\''; $query = 'DELETE FROM project WHERE id=\'' . $projectID . '\'';
$statement = $pdo->prepare($query); $statement = $pdo->prepare($query);
$statement->execute(); $statement->execute();

View File

@@ -37,13 +37,18 @@ if (isset($_GET['id'])) {
} }
$project = new pvv\side\Project( $project = new pvv\side\Project(
0, id: 0,
'Kult Prosjekt', title: 'Kult Prosjekt',
'', description_en: '',
'kåre knoll', description_no: '',
'pvvadmin', gitea_link: 'https://git.pvv.ntnu.no/Projects/kultprosjekt',
'drift@pvv.ntnu.no', issue_board_link: 'https://git.pvv.ntnu.no/Projects/kultprosjekt/issues',
0 wiki_link: 'https://wiki.pvv.ntnu.no/wiki/Kult_Prosjekt',
programming_languages: 'PHP, HTML, CSS, JavaScript',
technologies: 'MySQL, REST, AJAX',
keywords: 'web, very-cool',
license: 'GPL-3.0',
logo_url: '',
); );
if ($new == 0) { if ($new == 0) {
$project = $projectManager->getByID($projectID); $project = $projectManager->getByID($projectID);
@@ -56,7 +61,7 @@ $owner = [
'mail' => '', 'mail' => '',
]; ];
foreach ($members as $i => $data) { foreach ($members as $i => $data) {
if ($data['owner']) { if ($data['is_owner']) {
$owner = $data; $owner = $data;
} }
} }

View File

@@ -1,161 +1,92 @@
a.nostyle {
text-decoration: none;
color:inherit;
cursor: pointer;
}
.project-card { .project-card {
position: relative; position: relative;
display: flex;
flex-direction: column;
box-sizing: border-box; box-sizing: border-box;
border-radius: .15em; border-radius: .2em;
border: 0 solid #048; border-left: .3em solid #048;
border-left-width: .3em;
box-shadow: 0 .1em .3em -.1em rgba(0,0,0,0.5); box-shadow: 0 .1em .3em -.1em rgba(0,0,0,0.5);
overflow: hidden; background: #fff;
top: 0; min-height: 8em;
min-height: 6em; transition: box-shadow .15s ease, transform .15s ease;
margin: 0;
height: 100%;
} }
.project-card:hover { .project-card:hover {
box-shadow: 0.1em 0.2em 0.5em 0em rgba(0,0,0,0.5); box-shadow: 0.2em 0.3em 0.6em rgba(0,0,0,0.45);
transform: translateY(-2px);
}
/* Header */
.project-header {
display: flex;
align-items: center;
gap: .6em;
padding: .6em;
}
.project-logo {
width: 2.4em;
height: 2.4em;
object-fit: contain;
border-radius: .2em;
flex-shrink: 0;
} }
.project-title { .project-title {
padding-bottom: .1em;
margin: 0; margin: 0;
font-size: 1.05em;
text-overflow: ellipsis; text-overflow: ellipsis;
}
.card-content {
display: block;
margin: .6em;
margin-bottom: 0;
}
.card-content p {
line-height: 1.25em;
}
.card-content * {
margin-top: 0;
}
.project-organizer {
position: absolute;
bottom: 0;
right: 0;
margin: 0;
font-size: .8em;
text-align: right;
font-style: italic;
opacity: 0.5;
padding: 0.1em 0.4em;
}
.projects-container {
margin-top: 2em;
margin-bottom: 3em;
display: grid;
grid-template-columns: 1fr;
grid-column-gap: 0.5em;
grid-row-gap: 1.3em;
}
@media screen and (min-width: 60em) {
.projects-container {
grid-template-columns: 1fr 1fr;
}
}
@media screen and (min-width: 50rem) {
.contentsplit {
display: grid;
grid-template-columns: 17em 2.7fr;
grid-template-areas: "left right";
grid-column-gap: 0.9em;
}
}
@media screen and (max-width: 50rem) {
.contentsplit {
display: grid;
grid-template-rows: auto auto;
grid-template-areas: "right"
"left";
}
}
@media screen and (min-width: 33rem) and (max-width: 50rem) {
.projectmember-container {
display: grid;
grid-template-columns: 1fr 1fr;
grid-template-rows: auto auto;
grid-template-areas: "organizers members"
"join join";
}
}
.gridl {
grid-area: left;
}
.projectmember-container {
padding: 0.1em 1em;
box-shadow: 0 2px 10px 0 rgba(0,0,0,0.2);
}
.projectmember-container h2 {
text-align: center;
}
.projectmember-container >form {
text-align: center;
grid-area: join;
}
.gridr {
border-left: 0;
grid-area: right;
padding:0;
margin:0;
}
.projectmember {
margin-bottom: 1em;
padding: 0 .5em 0 .5em;
overflow: hidden; overflow: hidden;
border-left: 4px solid #35a; white-space: nowrap;
} }
.projectmember p { /* Content */
.card-content {
padding: 0 .6em .4em;
flex-grow: 1;
}
.project-description {
line-height: 1.3em;
margin: 0; margin: 0;
color: #333;
} }
.projectmember p { /* Tags */
font-size: .8em; .project-tags {
margin-top: .4em;
display: flex;
flex-wrap: wrap;
gap: .3em;
} }
.projectmember p:first-child { .tag {
font-size: 1em; font-size: .7em;
margin-bottom: .2em; padding: .15em .45em;
border-radius: .3em;
background: #eef3f7;
color: #345;
white-space: nowrap;
} }
.memberuname, .memberemail { /* Footer */
display: inline-block; .project-footer {
color: #888; display: flex;
justify-content: space-between;
align-items: center;
padding: .2em .5em;
font-size: .75em;
opacity: .7;
} }
.memberuname { .project-links a {
float: left; margin-left: .4em;
text-decoration: none;
opacity: .7;
} }
.memberemail { .project-links a:hover {
float: right; opacity: 1;
}
@media screen and (max-width: 50rem) {
.projects {
display: inline-block;
}
} }
/* edit */ /* edit */

View File

@@ -14,31 +14,37 @@ $pdo = new PDO($DB_DSN, $DB_USER, $DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$projectManager = new pvv\side\ProjectManager($pdo); $projectManager = new pvv\side\ProjectManager($pdo);
$new = 0; $project_is_new = false;
if (isset($_GET['new'])) { if (isset($_GET['new'])) {
$new = $_GET['new']; $project_is_new = $_GET['new'];
} }
$projectID = 0; $projectID = 0;
if (isset($_GET['id'])) { if (isset($_GET['id'])) {
$projectID = $_GET['id']; $projectID = $_GET['id'];
} elseif ($new == 0) { } elseif (!$project_is_new) {
echo "\nID not set"; echo "\nID not set";
exit; exit;
} }
$project = new pvv\side\Project( $project = new pvv\side\Project(
0, id: 0,
'Nytt Prosjekt', title: 'Nytt Prosjekt',
'', description_en: null,
$attrs['cn'][0], description_no: null,
$attrs['uid'][0], gitea_link: null,
$attrs['mail'][0], issue_board_link: null,
1 wiki_link: null,
programming_languages: null,
technologies: null,
keywords: null,
license: null,
logo_url: null
); );
if ($new == 0) {
if (!$project_is_new) {
$project = $projectManager->getByID($projectID); $project = $projectManager->getByID($projectID);
$owner = $projectManager->getProjectOwner($projectID); $maintainers = $projectManager->getProjectMaintainers($projectID);
if ($owner['uname'] != $attrs['uid'][0]) { if ($owner['uname'] != $attrs['uid'][0]) {
header('HTTP/1.0 403 Forbidden'); header('HTTP/1.0 403 Forbidden');
@@ -46,6 +52,7 @@ if ($new == 0) {
exit; exit;
} }
} }
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="no"> <html lang="no">
@@ -74,20 +81,56 @@ if ($new == 0) {
<form action="update.php", method="post"> <form action="update.php", method="post">
<p class="subtitle no-chin">Prosjektnavn</p> <p class="subtitle no-chin">Prosjektnavn</p>
<p class="subnote">Gi prosjektet ditt et passende navn</p> <p class="subnote">Gi prosjektet ditt et passende navn</p>
<input class="wide" type="text" name="title" value="<?php echo $project->getName(); ?>" class="boxinput"><br> <input class="wide" type="text" name="title" value="<?php echo $project->getTitle(); ?>" class="boxinput" required><br>
<p class="subtitle no-chin">Beskrivelse (<i style="opacity:0.5;">markdown</i>)</p> <p class="subtitle no-chin">Beskrivelse (<i style="opacity:0.5;">markdown</i>)</p>
<p class="subnote no-chin">Hva går prosjektet ditt ut på?</p> <p class="subnote no-chin">Hva går prosjektet ditt ut på?</p>
<p class="subnote">De første to linjene blir vist på prosjektkortet, prøv å gjøre de til et fint sammendrag eller intro!</p> <p class="subnote">De første to linjene blir vist på prosjektkortet, prøv å gjøre de til et fint sammendrag eller intro!</p>
<textarea class="tall" name="desc" style="width:100%" rows="8" class="boxinput"><?php echo implode("\n", $project->getDescription()); ?></textarea> <textarea class="tall" name="desc_no" style="width:100%" rows="8" class="boxinput" required><?php echo implode("\n", $project->getDescriptionNo()); ?></textarea>
<p class="subtitle no-chin">Beskrivelse på engelsk (<i style="opacity:0.5;">markdown</i>)</p>
<p class="subnote no-chin">Gjenta på engelsk</p>
<textarea class="tall" name="desc_en" style="width:100%" rows="8" class="boxinput" required><?php echo implode("\n", $project->getDescriptionEn()); ?></textarea>
<p class="subtitle no-chin">Gitea-link</p>
<p class="subnote">Link til prosjektet på Gitea</p>
<input class="wide" type="text" name="gitea" value="<?php echo $project->getGiteaLink(); ?>" class="boxinput"><br>
<p class="subtitle no-chin">Issue board-link</p>
<p class="subnote">Link til issue board på Gitea</p>
<input class="wide" type="text" name="issue" value="<?php echo $project->getIssueBoardLink(); ?>" class="boxinput"><br>
<p class="subtitle no-chin">Wiki-link</p>
<p class="subnote">Link til wiki-side</p>
<input class="wide" type="text" name="wiki" value="<?php echo $project->getWikiLink(); ?>" class="boxinput"><br>
<p class="subtitle no-chin">Programmeringsspråk</p>
<p class="subnote">Hvilke programmeringsspråk brukes i prosjektet?</p>
<input class="wide" type="text" name="langs" value="<?php echo implode("\n", $project->getProgrammingLanguages()); ?>" class="boxinput"><br>
<p class="subtitle no-chin">Teknologier</p>
<p class="subnote">Hvilke teknologier brukes i prosjektet?</p>
<input class="wide" type="text" name="techs" value="<?php echo implode("\n", $project->getTechnologies()); ?>" class="boxinput"><br>
<p class="subtitle no-chin">Nøkkelord</p>
<p class="subnote">Nøkkelord som beskriver prosjektet</p>
<input class="wide" type="text" name="keywords" value="<?php echo implode("\n", $project->getKeywords()); ?>" class="boxinput"><br>
<p class="subtitle no-chin">Lisens</p>
<p class="subnote">Hvilken lisens bruker prosjektet?</p>
<input class="wide" type="text" name="license" value="<?php echo $project->getLicense(); ?>" class="boxinput"><br>
<p class="subtitle no-chin">Logo-URL</p>
<p class="subnote">Link til logo for prosjektet</p>
<input class="wide" type="text" name="logo" value="<?php echo $project->getLogoURL(); ?>" class="boxinput"><br>
<?php echo '<input type="hidden" name="id" value="' . $project->getID() . '" />'; ?> <?php echo '<input type="hidden" name="id" value="' . $project->getID() . '" />'; ?>
<input type="hidden" name="active" value="1"/> <input type="hidden" name="active" value="1"/>
<div style="margin-top: 0.2em;"> <div style="margin-top: 0.2em;">
<hr class="ruler"> <hr class="ruler">
<input type="submit" class="btn" value="<?php echo $new ? 'Opprett prosjekt' : 'Lagre endringer'; ?>"></input> <input type="submit" class="btn" value="<?php echo $project_is_new ? 'Opprett prosjekt' : 'Lagre endringer'; ?>"></input>
<?php if (!$new) {?><input type="submit" class="btn" name="delete" value="Slett"></input><?php } ?> <?php if (!$project_is_new) {?><input type="submit" class="btn" name="delete" value="Slett"></input><?php } ?>
</div> </div>
</form> </form>
</main> </main>

View File

@@ -71,7 +71,6 @@ $projects = $projectManager->getAll();
<br> <br>
<center> <center>
<a class="btn" href="edit.php?new=1">Lag prosjekt</a> <a class="btn" href="edit.php?new=1">Lag prosjekt</a>
<a class="btn" href="mine.php">Mine prosjekter</a>
</center> </center>
<br> <br>
<?php <?php
@@ -84,7 +83,7 @@ $projects = $projectManager->getAll();
<div class="projects-container"> <div class="projects-container">
<?php <?php
$randProjects = array_rand($projects, min(6, count($projects))); $randProjects = array_rand($projects, min(8, count($projects)));
if (!is_array($randProjects)) { if (!is_array($randProjects)) {
$randProjects = [$randProjects]; $randProjects = [$randProjects];
} }
@@ -93,16 +92,60 @@ $projects = $projectManager->getAll();
$owner = $projectManager->getProjectOwner($project->getID()); $owner = $projectManager->getProjectOwner($project->getID());
?> ?>
<a class="nostyle" href="info.php?id=<?php echo $project->getID(); ?>"><div class="project-card"> <a class="nostyle" href="info.php?id=<?php echo $project->getID(); ?>">
<article class="project-card">
<header class="project-header">
<?php if (!empty($project->getLogoURL())): ?>
<img src="<?php echo htmlspecialchars($project->getLogoURL()); ?>"
alt=""
class="project-logo">
<?php endif; ?>
<h4 class="project-title">
<?php echo htmlspecialchars($project->getTitle()); ?>
</h4>
</header>
<div class="card-content"> <div class="card-content">
<h4 class="project-title"><?php echo $project->getName(); ?></h4> <p class="project-description">
<?php <?php
$Parsedown = new Parsedown(); $Parsedown = new Parsedown();
echo $Parsedown->text(implode("\n", array_slice($project->getDescription(), 0, 2))); echo $Parsedown->text(
implode("\n", $project->getDescriptionEn())
);
?> ?>
</p>
<?php if (!empty($project->getTechnologies())): ?>
<div class="project-tags">
<?php foreach ($project->getTechnologies() as $tech): ?>
<span class="tag"><?php echo trim($tech); ?></span>
<?php endforeach; ?>
</div> </div>
<p class="project-organizer">Organisert av <?php echo $owner['name']; ?></p> <?php endif; ?>
</div></a> </div>
<footer class="project-footer">
<span class="project-organizer">
Organisert av <?php echo htmlspecialchars($owner['name']); ?>
</span>
<div class="project-links">
<?php if ($project->getGiteaLink()): ?>
<a href="<?php echo $project->getGiteaLink(); ?>" title="Repository"></a>
<?php endif; ?>
<?php if ($project->getIssueBoardLink()): ?>
<a href="<?php echo $project->getIssueBoardLink(); ?>" title="Issues">🐞</a>
<?php endif; ?>
<?php if ($project->getWikiLink()): ?>
<a href="<?php echo $project->getWikiLink(); ?>" title="Wiki">📖</a>
<?php endif; ?>
</div>
</footer>
</article>
</a>
<?php } ?> <?php } ?>
</div> </div>
<center> <center>

View File

@@ -1,120 +0,0 @@
<?php
date_default_timezone_set('Europe/Oslo');
setlocale(\LC_ALL, 'nb_NO');
require __DIR__ . '/../../inc/navbar.php';
require __DIR__ . '/../../src/_autoload.php';
require __DIR__ . '/../../config.php';
require_once __DIR__ . '/../../vendor/simplesamlphp/simplesamlphp/lib/_autoload.php';
$as = new SimpleSAML\Auth\Simple('default-sp');
$as->requireAuth();
$attrs = $as->getAttributes();
$pdo = new PDO($DB_DSN, $DB_USER, $DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
$projectManager = new pvv\side\ProjectManager($pdo);
$projects = $projectManager->getByOwner($attrs['uid'][0]);
$page = 1;
if (isset($_GET['page'])) {
$page = $_GET['page'];
}
$filter = '';
if (isset($_GET['filter'])) {
$filter = $_GET['filter'];
}
// filter
$projects = array_values(array_filter(
$projects,
static fn($project) => (preg_match('/.*' . $filter . '.*/i', $project->getName()) || preg_match('/.*' . $filter . '.*/i', implode(' ', $project->getDescription())))
));
?>
<!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/events.css">
<link rel="stylesheet" href="../css/admin.css">
<meta name="theme-color" content="#024" />
<title>Prosjektverkstedet</title>
<header>Prosjekt&shy;verk&shy;stedet</header>
<body>
<nav>
<?php echo navbar(1, 'prosjekt'); ?>
<?php echo loginbar(); ?>
</nav>
<main class="gridsplit">
<div class="gridl">
<h2 class="no-chin">Mine Prosjekter</h2>
<ul class="event-list">
<?php
$counter = 0;
$pageLimit = 8;
for ($i = ($pageLimit * ($page - 1)); $i < count($projects); ++$i) {
if ($counter == $pageLimit) {
break;
}
$project = $projects[$i];
$projectID = $project->getID();
$owner = $projectManager->getProjectOwner($projectID);
if ($owner['uname'] != $attrs['uid'][0]) {
continue;
}
?>
<li>
<div class="event">
<div class="event-info">
<a href="edit.php?id=<?php echo $project->getID(); ?>">
<h3 class="no-chin"><?php echo $project->getName(); ?></h3>
</a>
<p style="text-decoration: none;"><?php echo implode('<br>', array_slice($project->getDescription(), 0, 4)); ?></p>
</div>
</div>
</li>
<?php
++$counter;
}
?>
</ul>
<?php
if ($page != 1) {
echo '<a class="btn float-left" href="?page=' . ($page - 1) . '&filter=' . urlencode($filter) . '">Forrige side</a>';
}
if (($counter == $pageLimit) && (($pageLimit * $page) < count($projects))) {
echo '<a class="btn float-right" href="?page=' . ($page + 1) . '&filter=' . urlencode($filter) . '">Neste side</a>';
}
?>
</div>
<div class="gridr">
<h2>Verktøy</h2>
<a class="btn" href="edit.php?new=1">Lag prosjekt</a>
<h2>Filter</h2>
<form action="mine.php" method="get">
<p class="no-chin">Navn</p>
<?php echo '<input type="text" name="filter" class="boxinput" value="' . $filter . '">'; ?><br>
<div style="margin-top: 2em;">
<input type="submit" class="btn" value="Filtrer"></input>
</div>
</form>
</div>
</main>
</body>

View File

@@ -6,48 +6,125 @@ require __DIR__ . '/../../config.php';
$pdo = new PDO($DB_DSN, $DB_USER, $DB_PASS); $pdo = new PDO($DB_DSN, $DB_USER, $DB_PASS);
$pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); $pdo->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION);
if (!isset($_POST['title']) || !isset($_POST['desc']) || !isset($_POST['active'])) { $required_fields = [
'title',
'desc_no',
'desc_en',
'gitea',
'issue',
'wiki',
'langs',
'techs',
'keywords',
'license',
'logo'
];
foreach ($required_fields as $field) {
if (!isset($_POST[$field])) {
header('Location: ' . $_SERVER['HTTP_REFERER']); header('Location: ' . $_SERVER['HTTP_REFERER']);
exit; exit;
} }
}
require_once __DIR__ . '/../../vendor/simplesamlphp/simplesamlphp/lib/_autoload.php'; require_once __DIR__ . '/../../vendor/simplesamlphp/simplesamlphp/lib/_autoload.php';
$as = new SimpleSAML\Auth\Simple('default-sp'); $as = new SimpleSAML\Auth\Simple('default-sp');
$as->requireAuth(); $as->requireAuth();
$attrs = $as->getAttributes(); $attrs = $as->getAttributes();
$id = $_POST['id']; $id = $_POST['id'] ?? 0;
$do_delete = isset($_POST['delete']); $do_delete = isset($_POST['delete']);
$do_join_or_leave = isset($_POST['join_or_leave']); $do_join_or_leave = isset($_POST['join_or_leave']);
$active = $_POST['active'];
$title = $_POST['title']; $title = $_POST['title'];
$desc = $_POST['desc']; $desc_no = $_POST['desc_no'];
$desc_en = $_POST['desc_en'];
$gitea = $_POST['gitea'];
$issue = $_POST['issue'];
$wiki = $_POST['wiki'];
$langs = $_POST['langs'];
$techs = $_POST['techs'];
$keywords = $_POST['keywords'];
$license = $_POST['license'];
$logo = $_POST['logo'];
$name = $attrs['cn'][0]; $name = $attrs['cn'][0];
$uname = $attrs['uid'][0]; $uname = $attrs['uid'][0];
$mail = $attrs['mail'][0]; $mail = $attrs['mail'][0];
if ($id == 0) { // Create new project
if ($id == 0) { $query = <<<END
$query = 'INSERT INTO projects (name, description, active) VALUES (:title, :desc, TRUE)'; INSERT INTO
project(
title,
description_no,
description_en,
gitea_link,
issue_board_link,
wiki_link,
languages,
technologies,
keywords,
license,
logo_url
)
VALUES
(
:title,
:desc_no,
:desc_en,
:gitea,
:issue,
:wiki,
:langs,
:techs,
:keywords,
:license,
:logo
)
END;
$statement = $pdo->prepare($query); $statement = $pdo->prepare($query);
$statement->bindParam(':title', $title, PDO::PARAM_STR); $statement->bindParam(':title', $title, PDO::PARAM_STR);
$statement->bindParam(':desc', $desc, PDO::PARAM_STR); $statement->bindParam(':desc_no', $desc_no, PDO::PARAM_STR);
$statement->bindParam(':desc_en', $desc_en, PDO::PARAM_STR);
$statement->bindParam(':gitea', $gitea, PDO::PARAM_STR);
$statement->bindParam(':issue', $issue, PDO::PARAM_STR);
$statement->bindParam(':wiki', $wiki, PDO::PARAM_STR);
$statement->bindParam(':langs', $langs, PDO::PARAM_STR);
$statement->bindParam(':techs', $techs, PDO::PARAM_STR);
$statement->bindParam(':keywords', $keywords, PDO::PARAM_STR);
$statement->bindParam(':license', $license, PDO::PARAM_STR);
$statement->bindParam(':logo', $logo, PDO::PARAM_STR);
$statement->execute(); $statement->execute();
$new_id = $pdo->lastInsertId(); $new_project_id = $pdo->lastInsertId();
$ownerQuery = <<<END
INSERT INTO
project_maintainer (
uname,
project_id,
name,
email
)
VALUES
(
:username,
:project_id,
:user_real_name,
:user_email
)
END;
$ownerQuery = "INSERT INTO projectmembers (projectid, name, uname, mail, role, lead, owner) VALUES (:id, :owner, :owneruname, :owneremail, 'Prosjektleder', TRUE, TRUE)";
$statement = $pdo->prepare($ownerQuery); $statement = $pdo->prepare($ownerQuery);
$statement->bindParam(':id', $new_id, PDO::PARAM_STR); $statement->bindParam(':username', $uname, PDO::PARAM_STR);
$statement->bindParam(':owner', $name, PDO::PARAM_STR); $statement->bindParam(':project_id', $new_project_id, PDO::PARAM_INT);
$statement->bindParam(':owneruname', $uname, PDO::PARAM_STR); $statement->bindParam(':user_real_name', $name, PDO::PARAM_STR);
$statement->bindParam(':owneremail', $mail, PDO::PARAM_STR); $statement->bindParam(':user_email', $mail, PDO::PARAM_STR);
$statement->execute(); $statement->execute();
} else { } else { // Update existing project
$projectManager = new pvv\side\ProjectManager($pdo); $projectManager = new pvv\side\ProjectManager($pdo);
$owner = $projectManager->getProjectOwner($id); $owner = $projectManager->getProjectOwner($id);
$members = $projectManager->getProjectMembers($id); $members = $projectManager->getProjectMembers($id);