7 Commits

20 changed files with 1254 additions and 742 deletions
Generated
+149 -156
View File
@@ -287,16 +287,16 @@
}, },
{ {
"name": "guzzlehttp/psr7", "name": "guzzlehttp/psr7",
"version": "2.10.3", "version": "2.9.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/guzzle/psr7.git", "url": "https://github.com/guzzle/psr7.git",
"reference": "7c1472269227dc6f18930bd903d7a88fe6c52130" "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/guzzle/psr7/zipball/7c1472269227dc6f18930bd903d7a88fe6c52130", "url": "https://api.github.com/repos/guzzle/psr7/zipball/7d0ed42f28e42d61352a7a79de682e5e67fec884",
"reference": "7c1472269227dc6f18930bd903d7a88fe6c52130", "reference": "7d0ed42f28e42d61352a7a79de682e5e67fec884",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -311,9 +311,9 @@
}, },
"require-dev": { "require-dev": {
"bamarni/composer-bin-plugin": "^1.8.2", "bamarni/composer-bin-plugin": "^1.8.2",
"http-interop/http-factory-tests": "1.1.0", "http-interop/http-factory-tests": "0.9.0",
"jshttp/mime-db": "1.54.0.1", "jshttp/mime-db": "1.54.0.1",
"phpunit/phpunit": "^8.5.52 || ^9.6.34" "phpunit/phpunit": "^8.5.44 || ^9.6.25"
}, },
"suggest": { "suggest": {
"laminas/laminas-httphandlerrunner": "Emit PSR-7 responses" "laminas/laminas-httphandlerrunner": "Emit PSR-7 responses"
@@ -384,7 +384,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/guzzle/psr7/issues", "issues": "https://github.com/guzzle/psr7/issues",
"source": "https://github.com/guzzle/psr7/tree/2.10.3" "source": "https://github.com/guzzle/psr7/tree/2.9.0"
}, },
"funding": [ "funding": [
{ {
@@ -400,7 +400,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-27T11:48:20+00:00" "time": "2026-03-10T16:41:02+00:00"
}, },
{ {
"name": "nyholm/psr7", "name": "nyholm/psr7",
@@ -1152,16 +1152,16 @@
}, },
{ {
"name": "simplesamlphp/saml2", "name": "simplesamlphp/saml2",
"version": "v6.2.1", "version": "v6.2.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/simplesamlphp/saml2.git", "url": "https://github.com/simplesamlphp/saml2.git",
"reference": "f3c4d4fbe44639e63a94e023e7198e5d243d6422" "reference": "8be7855cced8a43a474cfc8062e85b328c06f3ff"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/f3c4d4fbe44639e63a94e023e7198e5d243d6422", "url": "https://api.github.com/repos/simplesamlphp/saml2/zipball/8be7855cced8a43a474cfc8062e85b328c06f3ff",
"reference": "f3c4d4fbe44639e63a94e023e7198e5d243d6422", "reference": "8be7855cced8a43a474cfc8062e85b328c06f3ff",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1176,7 +1176,6 @@
"psr/clock": "~1.0", "psr/clock": "~1.0",
"psr/http-message": "~2.0", "psr/http-message": "~2.0",
"psr/log": "~3.0", "psr/log": "~3.0",
"robrichards/xmlseclibs": "^3.1",
"simplesamlphp/assert": "~2.0", "simplesamlphp/assert": "~2.0",
"simplesamlphp/xml-common": "~2.8", "simplesamlphp/xml-common": "~2.8",
"simplesamlphp/xml-security": "~2.3", "simplesamlphp/xml-security": "~2.3",
@@ -1185,9 +1184,7 @@
"require-dev": { "require-dev": {
"beste/clock": "~3.0", "beste/clock": "~3.0",
"ext-intl": "*", "ext-intl": "*",
"icanhazstring/composer-unused": "^0.9.6",
"mockery/mockery": "~1.6", "mockery/mockery": "~1.6",
"simplesamlphp/simplesamlphp": "2.5.*",
"simplesamlphp/simplesamlphp-test-framework": "~1.11" "simplesamlphp/simplesamlphp-test-framework": "~1.11"
}, },
"suggest": { "suggest": {
@@ -1225,22 +1222,22 @@
"description": "SAML2 PHP library from SimpleSAMLphp", "description": "SAML2 PHP library from SimpleSAMLphp",
"support": { "support": {
"issues": "https://github.com/simplesamlphp/saml2/issues", "issues": "https://github.com/simplesamlphp/saml2/issues",
"source": "https://github.com/simplesamlphp/saml2/tree/v6.2.1" "source": "https://github.com/simplesamlphp/saml2/tree/v6.2.0"
}, },
"time": "2026-05-25T14:44:15+00:00" "time": "2026-04-23T23:20:37+00:00"
}, },
{ {
"name": "simplesamlphp/saml2-legacy", "name": "simplesamlphp/saml2-legacy",
"version": "v4.20.3", "version": "v4.20.1",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/simplesamlphp/saml2-legacy.git", "url": "https://github.com/simplesamlphp/saml2-legacy.git",
"reference": "b43d5d10ea1180f478ddcd677ff13bb324cfa866" "reference": "ac325057307cc8765e190fae20f7721d5f7b9f69"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/simplesamlphp/saml2-legacy/zipball/b43d5d10ea1180f478ddcd677ff13bb324cfa866", "url": "https://api.github.com/repos/simplesamlphp/saml2-legacy/zipball/ac325057307cc8765e190fae20f7721d5f7b9f69",
"reference": "b43d5d10ea1180f478ddcd677ff13bb324cfa866", "reference": "ac325057307cc8765e190fae20f7721d5f7b9f69",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1263,7 +1260,7 @@
"type": "library", "type": "library",
"extra": { "extra": {
"branch-alias": { "branch-alias": {
"dev-master": "v4.20.x-dev" "dev-master": "v4.2.x-dev"
} }
}, },
"autoload": { "autoload": {
@@ -1283,9 +1280,9 @@
], ],
"description": "SAML2 PHP library from SimpleSAMLphp", "description": "SAML2 PHP library from SimpleSAMLphp",
"support": { "support": {
"source": "https://github.com/simplesamlphp/saml2-legacy/tree/v4.20.3" "source": "https://github.com/simplesamlphp/saml2-legacy/tree/v4.20.1"
}, },
"time": "2026-05-25T16:06:14+00:00" "time": "2026-03-13T12:39:43+00:00"
}, },
{ {
"name": "simplesamlphp/simplesamlphp", "name": "simplesamlphp/simplesamlphp",
@@ -1650,16 +1647,16 @@
}, },
{ {
"name": "symfony/cache", "name": "symfony/cache",
"version": "v7.4.13", "version": "v7.4.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/cache.git", "url": "https://github.com/symfony/cache.git",
"reference": "4c09e18a92cce126cc0d1155825279fca8cd0673" "reference": "8c5fbb4b5bc7a878f7ce66f1b7e29653c404984b"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/cache/zipball/4c09e18a92cce126cc0d1155825279fca8cd0673", "url": "https://api.github.com/repos/symfony/cache/zipball/8c5fbb4b5bc7a878f7ce66f1b7e29653c404984b",
"reference": "4c09e18a92cce126cc0d1155825279fca8cd0673", "reference": "8c5fbb4b5bc7a878f7ce66f1b7e29653c404984b",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1730,7 +1727,7 @@
"psr6" "psr6"
], ],
"support": { "support": {
"source": "https://github.com/symfony/cache/tree/v7.4.13" "source": "https://github.com/symfony/cache/tree/v7.4.10"
}, },
"funding": [ "funding": [
{ {
@@ -1750,7 +1747,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-24T08:43:14+00:00" "time": "2026-05-05T08:23:16+00:00"
}, },
{ {
"name": "symfony/cache-contracts", "name": "symfony/cache-contracts",
@@ -1913,16 +1910,16 @@
}, },
{ {
"name": "symfony/console", "name": "symfony/console",
"version": "v7.4.13", "version": "v7.4.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/console.git", "url": "https://github.com/symfony/console.git",
"reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217" "reference": "d7d2b64a45a89d607865927b176fa51c33ddbb58"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/console/zipball/85095d2573eaefaf35e40b9513a9bf09f72cd217", "url": "https://api.github.com/repos/symfony/console/zipball/d7d2b64a45a89d607865927b176fa51c33ddbb58",
"reference": "85095d2573eaefaf35e40b9513a9bf09f72cd217", "reference": "d7d2b64a45a89d607865927b176fa51c33ddbb58",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -1987,7 +1984,7 @@
"terminal" "terminal"
], ],
"support": { "support": {
"source": "https://github.com/symfony/console/tree/v7.4.13" "source": "https://github.com/symfony/console/tree/v7.4.9"
}, },
"funding": [ "funding": [
{ {
@@ -2007,20 +2004,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-24T08:56:14+00:00" "time": "2026-04-22T15:21:55+00:00"
}, },
{ {
"name": "symfony/dependency-injection", "name": "symfony/dependency-injection",
"version": "v7.4.13", "version": "v7.4.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/dependency-injection.git", "url": "https://github.com/symfony/dependency-injection.git",
"reference": "f299e20ce983be6c0744952533c6dfeaaa1448e2" "reference": "4eb0d9dfa9d4f7c59216baf49b3ed6b1fb72293d"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/dependency-injection/zipball/f299e20ce983be6c0744952533c6dfeaaa1448e2", "url": "https://api.github.com/repos/symfony/dependency-injection/zipball/4eb0d9dfa9d4f7c59216baf49b3ed6b1fb72293d",
"reference": "f299e20ce983be6c0744952533c6dfeaaa1448e2", "reference": "4eb0d9dfa9d4f7c59216baf49b3ed6b1fb72293d",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2071,7 +2068,7 @@
"description": "Allows you to standardize and centralize the way objects are constructed in your application", "description": "Allows you to standardize and centralize the way objects are constructed in your application",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/dependency-injection/tree/v7.4.13" "source": "https://github.com/symfony/dependency-injection/tree/v7.4.10"
}, },
"funding": [ "funding": [
{ {
@@ -2091,7 +2088,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-20T14:07:29+00:00" "time": "2026-05-06T11:55:30+00:00"
}, },
{ {
"name": "symfony/deprecation-contracts", "name": "symfony/deprecation-contracts",
@@ -2480,16 +2477,16 @@
}, },
{ {
"name": "symfony/filesystem", "name": "symfony/filesystem",
"version": "v7.4.11", "version": "v7.4.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/filesystem.git", "url": "https://github.com/symfony/filesystem.git",
"reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50" "reference": "dcd8f96bcdc0f128ec406c765cc066c6035d1be3"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/filesystem/zipball/d721ea61b4a5fba8c5b6e7c1feda19efea144b50", "url": "https://api.github.com/repos/symfony/filesystem/zipball/dcd8f96bcdc0f128ec406c765cc066c6035d1be3",
"reference": "d721ea61b4a5fba8c5b6e7c1feda19efea144b50", "reference": "dcd8f96bcdc0f128ec406c765cc066c6035d1be3",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2526,7 +2523,7 @@
"description": "Provides basic utilities for the filesystem", "description": "Provides basic utilities for the filesystem",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/filesystem/tree/v7.4.11" "source": "https://github.com/symfony/filesystem/tree/v7.4.9"
}, },
"funding": [ "funding": [
{ {
@@ -2546,7 +2543,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-11T16:38:44+00:00" "time": "2026-04-18T13:18:21+00:00"
}, },
{ {
"name": "symfony/finder", "name": "symfony/finder",
@@ -2618,16 +2615,16 @@
}, },
{ {
"name": "symfony/framework-bundle", "name": "symfony/framework-bundle",
"version": "v7.4.13", "version": "v7.4.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/framework-bundle.git", "url": "https://github.com/symfony/framework-bundle.git",
"reference": "8be39c7bf9e6f58fe49c07927572a9df7c961c95" "reference": "4b9cb207d72b2e4793f28a3c62ea0865098bea20"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/framework-bundle/zipball/8be39c7bf9e6f58fe49c07927572a9df7c961c95", "url": "https://api.github.com/repos/symfony/framework-bundle/zipball/4b9cb207d72b2e4793f28a3c62ea0865098bea20",
"reference": "8be39c7bf9e6f58fe49c07927572a9df7c961c95", "reference": "4b9cb207d72b2e4793f28a3c62ea0865098bea20",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2752,7 +2749,7 @@
"description": "Provides a tight integration between Symfony components and the Symfony full-stack framework", "description": "Provides a tight integration between Symfony components and the Symfony full-stack framework",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/framework-bundle/tree/v7.4.13" "source": "https://github.com/symfony/framework-bundle/tree/v7.4.10"
}, },
"funding": [ "funding": [
{ {
@@ -2772,20 +2769,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-23T18:04:28+00:00" "time": "2026-05-05T11:48:54+00:00"
}, },
{ {
"name": "symfony/http-client", "name": "symfony/http-client",
"version": "v7.4.13", "version": "v7.4.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-client.git", "url": "https://github.com/symfony/http-client.git",
"reference": "e8a112b8415707265a7e614278136a9d92989a6a" "reference": "7e941c6abf4e3bf7dca160bf0e11ef36a9f832f6"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-client/zipball/e8a112b8415707265a7e614278136a9d92989a6a", "url": "https://api.github.com/repos/symfony/http-client/zipball/7e941c6abf4e3bf7dca160bf0e11ef36a9f832f6",
"reference": "e8a112b8415707265a7e614278136a9d92989a6a", "reference": "7e941c6abf4e3bf7dca160bf0e11ef36a9f832f6",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -2853,7 +2850,7 @@
"http" "http"
], ],
"support": { "support": {
"source": "https://github.com/symfony/http-client/tree/v7.4.13" "source": "https://github.com/symfony/http-client/tree/v7.4.9"
}, },
"funding": [ "funding": [
{ {
@@ -2873,7 +2870,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-24T09:57:54+00:00" "time": "2026-04-29T13:25:15+00:00"
}, },
{ {
"name": "symfony/http-client-contracts", "name": "symfony/http-client-contracts",
@@ -2959,16 +2956,16 @@
}, },
{ {
"name": "symfony/http-foundation", "name": "symfony/http-foundation",
"version": "v7.4.13", "version": "v7.4.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-foundation.git", "url": "https://github.com/symfony/http-foundation.git",
"reference": "bc354f47c62301e990b7874fa662326368508e2c" "reference": "9381209597ec66c25be154cbf2289076e64d1eab"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-foundation/zipball/bc354f47c62301e990b7874fa662326368508e2c", "url": "https://api.github.com/repos/symfony/http-foundation/zipball/9381209597ec66c25be154cbf2289076e64d1eab",
"reference": "bc354f47c62301e990b7874fa662326368508e2c", "reference": "9381209597ec66c25be154cbf2289076e64d1eab",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3017,7 +3014,7 @@
"description": "Defines an object-oriented layer for the HTTP specification", "description": "Defines an object-oriented layer for the HTTP specification",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-foundation/tree/v7.4.13" "source": "https://github.com/symfony/http-foundation/tree/v7.4.8"
}, },
"funding": [ "funding": [
{ {
@@ -3037,20 +3034,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-24T11:20:33+00:00" "time": "2026-03-24T13:12:05+00:00"
}, },
{ {
"name": "symfony/http-kernel", "name": "symfony/http-kernel",
"version": "v7.4.13", "version": "v7.4.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/http-kernel.git", "url": "https://github.com/symfony/http-kernel.git",
"reference": "9df847980c436451f4f51d1284491bb4356dd989" "reference": "23486f59234c6fd6e8f1bec97124f3829d686627"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/http-kernel/zipball/9df847980c436451f4f51d1284491bb4356dd989", "url": "https://api.github.com/repos/symfony/http-kernel/zipball/23486f59234c6fd6e8f1bec97124f3829d686627",
"reference": "9df847980c436451f4f51d1284491bb4356dd989", "reference": "23486f59234c6fd6e8f1bec97124f3829d686627",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3136,7 +3133,7 @@
"description": "Provides a structured process for converting a Request into a Response", "description": "Provides a structured process for converting a Request into a Response",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/http-kernel/tree/v7.4.13" "source": "https://github.com/symfony/http-kernel/tree/v7.4.10"
}, },
"funding": [ "funding": [
{ {
@@ -3156,7 +3153,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-27T08:31:43+00:00" "time": "2026-05-06T12:07:34+00:00"
}, },
{ {
"name": "symfony/intl", "name": "symfony/intl",
@@ -3409,16 +3406,16 @@
}, },
{ {
"name": "symfony/polyfill-intl-grapheme", "name": "symfony/polyfill-intl-grapheme",
"version": "v1.38.1", "version": "v1.37.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-grapheme.git", "url": "https://github.com/symfony/polyfill-intl-grapheme.git",
"reference": "e9247d281d694a5120554d9afaf54e070e88a603" "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/e9247d281d694a5120554d9afaf54e070e88a603", "url": "https://api.github.com/repos/symfony/polyfill-intl-grapheme/zipball/4864388bfbd3001ce88e234fab652acd91fdc57e",
"reference": "e9247d281d694a5120554d9afaf54e070e88a603", "reference": "4864388bfbd3001ce88e234fab652acd91fdc57e",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3467,7 +3464,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.38.1" "source": "https://github.com/symfony/polyfill-intl-grapheme/tree/v1.37.0"
}, },
"funding": [ "funding": [
{ {
@@ -3487,20 +3484,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-26T05:58:03+00:00" "time": "2026-04-26T13:13:48+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-icu", "name": "symfony/polyfill-intl-icu",
"version": "v1.38.0", "version": "v1.37.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-icu.git", "url": "https://github.com/symfony/polyfill-intl-icu.git",
"reference": "445c90e341fccda10311019cf82ff73bb7343945" "reference": "3510b63d07376b04e57e27e82607d468bb134f78"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/445c90e341fccda10311019cf82ff73bb7343945", "url": "https://api.github.com/repos/symfony/polyfill-intl-icu/zipball/3510b63d07376b04e57e27e82607d468bb134f78",
"reference": "445c90e341fccda10311019cf82ff73bb7343945", "reference": "3510b63d07376b04e57e27e82607d468bb134f78",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3555,7 +3552,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.38.0" "source": "https://github.com/symfony/polyfill-intl-icu/tree/v1.37.0"
}, },
"funding": [ "funding": [
{ {
@@ -3575,20 +3572,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-25T11:52:53+00:00" "time": "2026-04-10T16:50:15+00:00"
}, },
{ {
"name": "symfony/polyfill-intl-normalizer", "name": "symfony/polyfill-intl-normalizer",
"version": "v1.38.0", "version": "v1.37.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-intl-normalizer.git", "url": "https://github.com/symfony/polyfill-intl-normalizer.git",
"reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b" "reference": "3833d7255cc303546435cb650316bff708a1c75c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/2d446c214bdbe5b71bde5011b060a05fece3ae6b", "url": "https://api.github.com/repos/symfony/polyfill-intl-normalizer/zipball/3833d7255cc303546435cb650316bff708a1c75c",
"reference": "2d446c214bdbe5b71bde5011b060a05fece3ae6b", "reference": "3833d7255cc303546435cb650316bff708a1c75c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3640,7 +3637,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.38.0" "source": "https://github.com/symfony/polyfill-intl-normalizer/tree/v1.37.0"
}, },
"funding": [ "funding": [
{ {
@@ -3660,20 +3657,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-25T13:48:31+00:00" "time": "2024-09-09T11:45:10+00:00"
}, },
{ {
"name": "symfony/polyfill-mbstring", "name": "symfony/polyfill-mbstring",
"version": "v1.38.1", "version": "v1.37.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-mbstring.git", "url": "https://github.com/symfony/polyfill-mbstring.git",
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92" "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/14c5439eec4ccff081ac14eca2dc57feb2a66d92", "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/6a21eb99c6973357967f6ce3708cd55a6bec6315",
"reference": "14c5439eec4ccff081ac14eca2dc57feb2a66d92", "reference": "6a21eb99c6973357967f6ce3708cd55a6bec6315",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3725,7 +3722,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-mbstring/tree/v1.38.1" "source": "https://github.com/symfony/polyfill-mbstring/tree/v1.37.0"
}, },
"funding": [ "funding": [
{ {
@@ -3745,20 +3742,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-26T12:51:13+00:00" "time": "2026-04-10T17:25:58+00:00"
}, },
{ {
"name": "symfony/polyfill-php83", "name": "symfony/polyfill-php83",
"version": "v1.38.1", "version": "v1.37.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php83.git", "url": "https://github.com/symfony/polyfill-php83.git",
"reference": "8339098cae28673c15cce00d80734af0453054e2" "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/8339098cae28673c15cce00d80734af0453054e2", "url": "https://api.github.com/repos/symfony/polyfill-php83/zipball/3600c2cb22399e25bb226e4a135ce91eeb2a6149",
"reference": "8339098cae28673c15cce00d80734af0453054e2", "reference": "3600c2cb22399e25bb226e4a135ce91eeb2a6149",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3805,7 +3802,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php83/tree/v1.38.1" "source": "https://github.com/symfony/polyfill-php83/tree/v1.37.0"
}, },
"funding": [ "funding": [
{ {
@@ -3825,20 +3822,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-26T12:51:13+00:00" "time": "2026-04-10T17:25:58+00:00"
}, },
{ {
"name": "symfony/polyfill-php85", "name": "symfony/polyfill-php85",
"version": "v1.38.1", "version": "v1.37.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/polyfill-php85.git", "url": "https://github.com/symfony/polyfill-php85.git",
"reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1" "reference": "fcfa4973a9917cef23f2e38774da74a2b7d115ee"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", "url": "https://api.github.com/repos/symfony/polyfill-php85/zipball/fcfa4973a9917cef23f2e38774da74a2b7d115ee",
"reference": "ba2ba04f3352cfa2dcbbcb90aee13ed967f505b1", "reference": "fcfa4973a9917cef23f2e38774da74a2b7d115ee",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3885,7 +3882,7 @@
"shim" "shim"
], ],
"support": { "support": {
"source": "https://github.com/symfony/polyfill-php85/tree/v1.38.1" "source": "https://github.com/symfony/polyfill-php85/tree/v1.37.0"
}, },
"funding": [ "funding": [
{ {
@@ -3905,20 +3902,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-26T02:25:22+00:00" "time": "2026-04-26T13:10:57+00:00"
}, },
{ {
"name": "symfony/routing", "name": "symfony/routing",
"version": "v7.4.13", "version": "v7.4.9",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/routing.git", "url": "https://github.com/symfony/routing.git",
"reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d" "reference": "287771d8bc86eacb30678dd10eda6c64a859951f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/routing/zipball/3a162171bb008e5e0f15dce6581373a4c0e8390d", "url": "https://api.github.com/repos/symfony/routing/zipball/287771d8bc86eacb30678dd10eda6c64a859951f",
"reference": "3a162171bb008e5e0f15dce6581373a4c0e8390d", "reference": "287771d8bc86eacb30678dd10eda6c64a859951f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -3970,7 +3967,7 @@
"url" "url"
], ],
"support": { "support": {
"source": "https://github.com/symfony/routing/tree/v7.4.13" "source": "https://github.com/symfony/routing/tree/v7.4.9"
}, },
"funding": [ "funding": [
{ {
@@ -3990,7 +3987,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-24T11:20:33+00:00" "time": "2026-04-22T15:21:55+00:00"
}, },
{ {
"name": "symfony/service-contracts", "name": "symfony/service-contracts",
@@ -4081,16 +4078,16 @@
}, },
{ {
"name": "symfony/string", "name": "symfony/string",
"version": "v8.0.13", "version": "v8.0.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/string.git", "url": "https://github.com/symfony/string.git",
"reference": "f2e3e4d33579350d1b12001ef2872f86b27ed3dc" "reference": "ae9488f874d7603f9d2dfbf120203882b645d963"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/string/zipball/f2e3e4d33579350d1b12001ef2872f86b27ed3dc", "url": "https://api.github.com/repos/symfony/string/zipball/ae9488f874d7603f9d2dfbf120203882b645d963",
"reference": "f2e3e4d33579350d1b12001ef2872f86b27ed3dc", "reference": "ae9488f874d7603f9d2dfbf120203882b645d963",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4147,7 +4144,7 @@
"utf8" "utf8"
], ],
"support": { "support": {
"source": "https://github.com/symfony/string/tree/v8.0.13" "source": "https://github.com/symfony/string/tree/v8.0.8"
}, },
"funding": [ "funding": [
{ {
@@ -4167,7 +4164,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-23T18:05:53+00:00" "time": "2026-03-30T15:14:47+00:00"
}, },
{ {
"name": "symfony/translation-contracts", "name": "symfony/translation-contracts",
@@ -4253,16 +4250,16 @@
}, },
{ {
"name": "symfony/twig-bridge", "name": "symfony/twig-bridge",
"version": "v7.4.12", "version": "v7.4.8",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/twig-bridge.git", "url": "https://github.com/symfony/twig-bridge.git",
"reference": "81663873d946531129c76c65e80b681ce99c0e89" "reference": "ac43e7e59298ed1ce98c8d228b651d46e907d02c"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/twig-bridge/zipball/81663873d946531129c76c65e80b681ce99c0e89", "url": "https://api.github.com/repos/symfony/twig-bridge/zipball/ac43e7e59298ed1ce98c8d228b651d46e907d02c",
"reference": "81663873d946531129c76c65e80b681ce99c0e89", "reference": "ac43e7e59298ed1ce98c8d228b651d46e907d02c",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4278,7 +4275,7 @@
"symfony/form": "<6.4.32|>7,<7.3.10|>7.4,<7.4.4|>8.0,<8.0.4", "symfony/form": "<6.4.32|>7,<7.3.10|>7.4,<7.4.4|>8.0,<8.0.4",
"symfony/http-foundation": "<6.4", "symfony/http-foundation": "<6.4",
"symfony/http-kernel": "<6.4", "symfony/http-kernel": "<6.4",
"symfony/mime": "<6.4.37|>7,<7.4.9|>8.0,<8.0.9", "symfony/mime": "<6.4.36|>7,<7.4.8|>8.0,<8.0.8",
"symfony/serializer": "<6.4", "symfony/serializer": "<6.4",
"symfony/translation": "<6.4", "symfony/translation": "<6.4",
"symfony/workflow": "<6.4" "symfony/workflow": "<6.4"
@@ -4299,7 +4296,7 @@
"symfony/http-foundation": "^7.3|^8.0", "symfony/http-foundation": "^7.3|^8.0",
"symfony/http-kernel": "^6.4|^7.0|^8.0", "symfony/http-kernel": "^6.4|^7.0|^8.0",
"symfony/intl": "^6.4|^7.0|^8.0", "symfony/intl": "^6.4|^7.0|^8.0",
"symfony/mime": "^6.4.37|^7.4.9|^8.0.9", "symfony/mime": "^6.4.36|^7.4.8|^8.0.8",
"symfony/polyfill-intl-icu": "~1.0", "symfony/polyfill-intl-icu": "~1.0",
"symfony/property-info": "^6.4|^7.0|^8.0", "symfony/property-info": "^6.4|^7.0|^8.0",
"symfony/routing": "^6.4|^7.0|^8.0", "symfony/routing": "^6.4|^7.0|^8.0",
@@ -4344,7 +4341,7 @@
"description": "Provides integration for Twig with various Symfony components", "description": "Provides integration for Twig with various Symfony components",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/twig-bridge/tree/v7.4.12" "source": "https://github.com/symfony/twig-bridge/tree/v7.4.8"
}, },
"funding": [ "funding": [
{ {
@@ -4364,7 +4361,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-04-29T17:13:54+00:00" "time": "2026-03-30T15:17:09+00:00"
}, },
{ {
"name": "symfony/var-dumper", "name": "symfony/var-dumper",
@@ -4536,16 +4533,16 @@
}, },
{ {
"name": "symfony/yaml", "name": "symfony/yaml",
"version": "v7.4.13", "version": "v7.4.10",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/symfony/yaml.git", "url": "https://github.com/symfony/yaml.git",
"reference": "a7ec3b1156faf8815db7683ec7c1e7338e6f977c" "reference": "c660d6538545a3e8e65a5621ee3d7a6d352892c7"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/symfony/yaml/zipball/a7ec3b1156faf8815db7683ec7c1e7338e6f977c", "url": "https://api.github.com/repos/symfony/yaml/zipball/c660d6538545a3e8e65a5621ee3d7a6d352892c7",
"reference": "a7ec3b1156faf8815db7683ec7c1e7338e6f977c", "reference": "c660d6538545a3e8e65a5621ee3d7a6d352892c7",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4588,7 +4585,7 @@
"description": "Loads and dumps YAML files", "description": "Loads and dumps YAML files",
"homepage": "https://symfony.com", "homepage": "https://symfony.com",
"support": { "support": {
"source": "https://github.com/symfony/yaml/tree/v7.4.13" "source": "https://github.com/symfony/yaml/tree/v7.4.10"
}, },
"funding": [ "funding": [
{ {
@@ -4608,20 +4605,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-25T06:06:12+00:00" "time": "2026-05-05T08:01:55+00:00"
}, },
{ {
"name": "twig/intl-extra", "name": "twig/intl-extra",
"version": "v3.26.0", "version": "v3.24.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/intl-extra.git", "url": "https://github.com/twigphp/intl-extra.git",
"reference": "98f5ad5bff13230fcd2d834d9e79b50adf3ccda9" "reference": "32f15a38d45a8d0ec11bc8a3d97d3ac2a261499f"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/intl-extra/zipball/98f5ad5bff13230fcd2d834d9e79b50adf3ccda9", "url": "https://api.github.com/repos/twigphp/intl-extra/zipball/32f15a38d45a8d0ec11bc8a3d97d3ac2a261499f",
"reference": "98f5ad5bff13230fcd2d834d9e79b50adf3ccda9", "reference": "32f15a38d45a8d0ec11bc8a3d97d3ac2a261499f",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4660,7 +4657,7 @@
"twig" "twig"
], ],
"support": { "support": {
"source": "https://github.com/twigphp/intl-extra/tree/v3.26.0" "source": "https://github.com/twigphp/intl-extra/tree/v3.24.0"
}, },
"funding": [ "funding": [
{ {
@@ -4672,20 +4669,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-19T20:44:48+00:00" "time": "2026-01-17T13:57:47+00:00"
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v3.27.0", "version": "v3.24.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "04ae1bfe9463c816cf72ca0abe7eae2c77a9a9ed" "reference": "a6769aefb305efef849dc25c9fd1653358c148f0"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/04ae1bfe9463c816cf72ca0abe7eae2c77a9a9ed", "url": "https://api.github.com/repos/twigphp/Twig/zipball/a6769aefb305efef849dc25c9fd1653358c148f0",
"reference": "04ae1bfe9463c816cf72ca0abe7eae2c77a9a9ed", "reference": "a6769aefb305efef849dc25c9fd1653358c148f0",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4740,7 +4737,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/twigphp/Twig/issues", "issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.27.0" "source": "https://github.com/twigphp/Twig/tree/v3.24.0"
}, },
"funding": [ "funding": [
{ {
@@ -4752,20 +4749,20 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2026-05-27T13:05:51+00:00" "time": "2026-03-17T21:31:11+00:00"
}, },
{ {
"name": "webmozart/assert", "name": "webmozart/assert",
"version": "2.4.0", "version": "2.3.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/webmozarts/assert.git", "url": "https://github.com/webmozarts/assert.git",
"reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155" "reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/webmozarts/assert/zipball/9007ea6f45ecf352a9422b36644e4bfc039b9155", "url": "https://api.github.com/repos/webmozarts/assert/zipball/eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
"reference": "9007ea6f45ecf352a9422b36644e4bfc039b9155", "reference": "eb0d790f735ba6cff25c683a85a1da0eadeff9e4",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
@@ -4781,11 +4778,7 @@
}, },
"type": "library", "type": "library",
"extra": { "extra": {
"psalm": {
"pluginClass": "Webmozart\\Assert\\PsalmPlugin"
},
"branch-alias": { "branch-alias": {
"dev-master": "2.0-dev",
"dev-feature/2-0": "2.0-dev" "dev-feature/2-0": "2.0-dev"
} }
}, },
@@ -4816,9 +4809,9 @@
], ],
"support": { "support": {
"issues": "https://github.com/webmozarts/assert/issues", "issues": "https://github.com/webmozarts/assert/issues",
"source": "https://github.com/webmozarts/assert/tree/2.4.0" "source": "https://github.com/webmozarts/assert/tree/2.3.0"
}, },
"time": "2026-05-20T13:07:01+00:00" "time": "2026-04-11T10:33:05+00:00"
} }
], ],
"packages-dev": [], "packages-dev": [],
+41 -11
View File
@@ -8,22 +8,52 @@ 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 NOT NULL, `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
project_group (title, description_en, description_no, gitea_link, wiki_link)
VALUES
(
'Projects',
'Projects developed by members of PVV.',
'Prosjekter utviklet av medlemmer i PVV.',
'https://git.pvv.ntnu.no/Projects',
'https://wiki.pvv.ntnu.no/wiki/Programvareutvikling'
);
CREATE TABLE project (
`id` INTEGER PRIMARY KEY AUTO_INCREMENT, `id` INTEGER PRIMARY KEY AUTO_INCREMENT,
`projectid` INTEGER FOREIGN KEY REFERENCES projects(`id`), `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,
`programming_languages` TEXT,
`technologies` TEXT,
`keywords` TEXT,
`license` TEXT,
`logo_url` TEXT,
`is_hidden` BOOLEAN DEFAULT FALSE,
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, `name` TEXT NOT NULL,
`uname` TEXT NOT NULL REFERENCES users(`uname`), `email` TEXT,
`mail` TEXT, `is_organizer` BOOLEAN DEFAULT FALSE,
`role` TEXT, PRIMARY KEY (uname, project_id),
`lead` BOOLEAN NOT NULL DEFAULT FALSE, FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE
`owner` BOOLEAN NOT NULL DEFAULT FALSE
); );
CREATE TABLE users ( CREATE TABLE users (
+46 -12
View File
@@ -8,24 +8,58 @@ 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 NOT NULL, "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
project_group (title, description_en, description_no, gitea_link, wiki_link)
VALUES
(
'Projects',
'Projects developed by members of PVV.',
'Prosjekter utviklet av medlemmer i PVV.',
'https://git.pvv.ntnu.no/Projects',
'https://wiki.pvv.ntnu.no/wiki/Programvareutvikling'
);
CREATE TABLE "project" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT, "id" INTEGER PRIMARY KEY AUTOINCREMENT,
"projectid" INTEGER REFERENCES projects(id), "group_id" INTEGER NOT NULL DEFAULT 1,
"name" TEXT NOT NULL, "title" TEXT NOT NULL,
"uname" TEXT NOT NULL REFERENCES users(uname), "description_en" TEXT NOT NULL,
"mail" TEXT, "description_no" TEXT NOT NULL,
"role" TEXT, "gitea_link" TEXT,
"lead" BOOLEAN NOT NULL DEFAULT FALSE, "issue_board_link" TEXT,
"owner" BOOLEAN NOT NULL DEFAULT FALSE "wiki_link" TEXT,
"programming_languages" TEXT,
"technologies" TEXT,
"keywords" TEXT,
"license" TEXT,
"logo_url" TEXT,
"is_hidden" BOOLEAN DEFAULT FALSE,
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_organizer" BOOLEAN DEFAULT FALSE,
PRIMARY KEY (uname, project_id),
FOREIGN KEY (project_id) REFERENCES project (id) ON DELETE CASCADE
);
--
CREATE TABLE "users" ( CREATE TABLE "users" (
"id" INTEGER PRIMARY KEY AUTOINCREMENT, "id" INTEGER PRIMARY KEY AUTOINCREMENT,
"uname" TEXT NOT NULL UNIQUE, "uname" TEXT NOT NULL UNIQUE,
Generated
+3 -3
View File
@@ -2,11 +2,11 @@
"nodes": { "nodes": {
"nixpkgs": { "nixpkgs": {
"locked": { "locked": {
"lastModified": 1779786838, "lastModified": 1778458615,
"narHash": "sha256-0geHoGiR5f8qiXg+gO4rSF6Up6Var+kKqiOv9AO/uUc=", "narHash": "sha256-cY07EsdhBJ8tFXPzDYevgqxRev9ZLxFonuq9wmq5kwg=",
"owner": "NixOS", "owner": "NixOS",
"repo": "nixpkgs", "repo": "nixpkgs",
"rev": "f44f7788c891fbe5542177df78374f8cdab10e8f", "rev": "c6e5ca3c836a5f4dd9af9f2c1fc1c38f0fac988a",
"type": "github" "type": "github"
}, },
"original": { "original": {
+3 -3
View File
@@ -27,9 +27,9 @@ use pvv\side\Agenda;
$agenda = new Agenda([ $agenda = new Agenda([
// new \pvv\side\social\NerdepitsaActivity, // new \pvv\side\social\NerdepitsaActivity,
// new \pvv\side\social\AnimekveldActivity, // new \pvv\side\social\AnimekveldActivity,
// new pvv\side\social\HackekveldActivity(), new pvv\side\social\HackekveldActivity(),
// new pvv\side\social\BrettspillActivity(), new pvv\side\social\BrettspillActivity(),
// new pvv\side\social\DriftkveldActivity(), new pvv\side\social\DriftkveldActivity(),
new pvv\side\DBActivity($pdo), new pvv\side\DBActivity($pdo),
]); ]);
+1 -1
View File
@@ -22,7 +22,7 @@ php.buildComposerProject rec {
}; };
pname = "pvv-nettsiden"; pname = "pvv-nettsiden";
version = "0.0.1"; version = "0.0.1";
vendorHash = "sha256-3pDP0fh5bmxsx5aN332Q7Es4QD2VzYhD4fGcXFZcdbI="; vendorHash = "sha256-SxuKP7CCLXbTtKQ1seLpAqUje+SEAJ1R+gK09UW2T9k=";
passthru.simplesamlphpPath = "share/php/pvv-nettsiden/vendor/simplesamlphp/simplesamlphp"; passthru.simplesamlphpPath = "share/php/pvv-nettsiden/vendor/simplesamlphp/simplesamlphp";
+139 -15
View File
@@ -6,35 +6,159 @@ 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;
private bool $is_hidden;
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,
bool $is_hidden = false,
) { ) {
$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;
$this->is_hidden = $is_hidden;
} }
public function getID(): int { public function getID(): int {
return $this->id; return $this->id;
} }
public function getTitle(): string {
return $this->title;
}
/**
* @return string[]
*/
public function getDescriptionEn(): array {
return $this->description_en;
}
/**
* @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;
}
public function isHidden(): bool {
return $this->is_hidden;
}
}
class ProjectMaintainer {
private string $uname;
private string $name;
private string $email;
private bool $is_organizer;
public function __construct(
string $uname,
string $name,
string $email,
bool $is_organizer,
) {
$this->uname = $uname;
$this->name = $name;
$this->email = $email;
$this->is_organizer = $is_organizer;
}
public function getUname(): string {
return $this->uname;
}
public function getName(): string { public function getName(): string {
return $this->name; return $this->name;
} }
public function getEmail(): string {
public function getDescription(): array { return $this->email;
return $this->descr;
} }
public function isOrganizer(): bool {
public function getActive(): bool { return $this->is_organizer;
return $this->active;
} }
} }
+156 -58
View File
@@ -11,11 +11,30 @@ 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
id,
title,
description_en,
description_no,
gitea_link,
issue_board_link,
wiki_link,
programming_languages,
technologies,
keywords,
license,
logo_url,
is_hidden
FROM project
ORDER BY title ASC
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->execute(); $statement->execute();
@@ -23,9 +42,18 @@ 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['programming_languages'],
$dbProj['technologies'],
$dbProj['keywords'],
$dbProj['license'],
$dbProj['logo_url'],
(bool) $dbProj['is_hidden']
); );
$projects[] = $project; $projects[] = $project;
} }
@@ -33,8 +61,26 @@ 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
id,
title,
description_en,
description_no,
gitea_link,
issue_board_link,
wiki_link,
programming_languages,
technologies,
keywords,
license,
logo_url,
is_hidden
FROM project
WHERE id = :id
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindValue(':id', $id, \PDO::PARAM_INT); $statement->bindValue(':id', $id, \PDO::PARAM_INT);
$statement->execute(); $statement->execute();
@@ -46,87 +92,139 @@ 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['programming_languages'],
$dbProj['technologies'],
$dbProj['keywords'],
$dbProj['license'],
$dbProj['logo_url'],
(bool) $dbProj['is_hidden']
); );
} }
// TODO: groupid
/** /**
* @return Project[] * @return Project[]
*/ */
public function getByOwner(string $uname): array { public function getByMaintainer(string $uname): array {
$query = 'SELECT projectid FROM projectmembers WHERE uname=:uname'; $query = '
SELECT
project.id,
project.title
project.description_en,
project.description_no,
project.gitea_link,
project.issue_board_link,
project.wiki_link,
project.programming_languages,
project.technologies,
project.keywords,
project.license,
project.logo_url,
project.is_hidden
FROM project_maintainer
JOIN project ON project.id = project_maintainer.project_id
WHERE project_maintainer.uname = :uname
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindValue(':uname', $uname, \PDO::PARAM_STR); $statement->bindValue(':uname', $uname, \PDO::PARAM_STR);
$statement->execute(); $statement->execute();
$projectIDs = $statement->fetchAll(); $result = array_map(
$projects = []; function ($dbProj) {
foreach ($projectIDs as $id) { return new Project(
$id = $id['projectid'];
$query = 'SELECT * FROM projects WHERE id=:id';
$statement = $this->pdo->prepare($query);
$statement->bindValue(':id', $id, \PDO::PARAM_INT);
$statement->execute();
foreach ($statement->fetchAll() as $dbProj) {
$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['programming_languages'],
$dbProj['technologies'],
$dbProj['keywords'],
$dbProj['license'],
$dbProj['logo_url'],
(bool) $dbProj['is_hidden']
); );
$projects[] = $project; },
} $statement->fetchAll()
} );
return $projects; return $result;
} }
/** /**
* @return array<int,array> * @return ProjectMaintainer[]
*/ */
public function getProjectMembers(int $id): array { public function getProjectMaintainers(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_organizer
FROM project_maintainer
WHERE project_maintainer.project_id = :id
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindValue(':id', $id, \PDO::PARAM_STR); $statement->bindValue(':id', $project_id, \PDO::PARAM_STR);
$statement->execute(); $statement->execute();
$members = []; $result = array_map(
foreach ($statement->fetchAll() as $dbUsr) { function ($dbUsr) {
$members[] = [ return new ProjectMaintainer(
'name' => $dbUsr['name'], $dbUsr['uname'],
'uname' => $dbUsr['uname'], $dbUsr['name'],
'mail' => $dbUsr['mail'], $dbUsr['email'],
'role' => $dbUsr['role'], (bool)$dbUsr['is_organizer']
'lead' => (bool) $dbUsr['lead'], );
'owner' => (bool) $dbUsr['owner'], },
]; $statement->fetchAll()
} );
return $members; return $result;
} }
/** /**
* @return array<string,mixed> * @return ProjectMaintainer[]
*/ */
public function getProjectOwner(int $id): array { public function getProjectOrganizers(int $project_id): array {
$query = 'SELECT * FROM projectmembers WHERE (projectid=:id AND owner=1)'; $query = '
SELECT
project_maintainer.uname,
project_maintainer.name,
project_maintainer.email,
project_maintainer.is_organizer
FROM project_maintainer
WHERE
project_maintainer.project_id = :id
AND project_maintainer.is_organizer = True
';
$statement = $this->pdo->prepare($query); $statement = $this->pdo->prepare($query);
$statement->bindValue(':id', $id, \PDO::PARAM_STR); $statement->bindValue(':id', $project_id, \PDO::PARAM_STR);
$statement->execute(); $statement->execute();
$dbOwner = $statement->fetch(); $result = array_map(
function ($dbUsr) {
return new ProjectMaintainer(
$dbUsr['uname'],
$dbUsr['name'],
$dbUsr['email'],
(bool)$dbUsr['is_organizer']
);
},
$statement->fetchAll()
);
return [ return $result;
'name' => $dbOwner['name'],
'uname' => $dbOwner['uname'],
'mail' => $dbOwner['mail'],
'role' => $dbOwner['role'],
'lead' => (bool) $dbOwner['lead'],
'owner' => (bool) $dbOwner['owner'],
];
} }
} }
+2 -1
View File
@@ -18,8 +18,9 @@ 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->bindValue(':projectID', $projectID, PDO::PARAM_INT);
$statement->execute(); $statement->execute();
header('Location: ' . $_SERVER['HTTP_REFERER']); header('Location: ' . $_SERVER['HTTP_REFERER']);
+13 -8
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;
} }
} }
+5 -5
View File
@@ -43,7 +43,7 @@ if(isset($_POST['organiser'])){
// filter // filter
$projects = array_values(array_filter( $projects = array_values(array_filter(
$projects, $projects,
static fn($project) => preg_match('/.*' . $filterTitle . '.*/i', $project->getName()) static fn($project) => preg_match('/.*' . $filterTitle . '.*/i', $project->getTitle())
)); ));
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
@@ -87,17 +87,17 @@ $projects = array_values(array_filter(
$project = $projects[$i]; $project = $projects[$i];
$projectID = $project->getID(); $projectID = $project->getID();
$owner = $projectManager->getProjectOwner($projectID); $organizers = $projectManager->getProjectOrganizers($projectID);
?> ?>
<li> <li>
<div class="event admin"> <div class="event admin">
<div class="event-info"> <div class="event-info">
<h3 class="no-chin"><?php echo $project->getName() . ' (ID: ' . $projectID . ')'; ?></h3> <h3 class="no-chin"><?php echo $project->getTitle() . ' (ID: ' . $projectID . ')'; ?></h3>
<p class="subnote"><?php echo 'Organisert av: ' . $owner['name']; ?></p> <p class="subnote"><?php echo 'Organisert av: ' . implode(',', array_map(function($org) { return $org->getName(); }, $organizers)); ?></p>
<?php <?php
$Parsedown = new Parsedown(); $Parsedown = new Parsedown();
echo $Parsedown->text(implode("\n", $project->getDescription())); echo $Parsedown->text(implode("\n", $project->getDescriptionNo()));
?> ?>
</div> </div>
+80 -133
View File
@@ -1,173 +1,120 @@
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 */
form .wide { form .wide {
min-width: 66%; min-width: 100%;
} }
form .tall { form .tall {
min-height: calc(100vh - 28em); min-height: calc(100vh - 28em);
} }
@media screen and (max-width: 50rem) { @media screen and (max-width: 50rem) {
form .wide { form .wide {
width: calc(100% - 2em); width: calc(100% - 2em);
margin: 0 1em; margin: 0 1em;
} }
} }
form .input-group {
display: flex;
}
form .input-group-item {
flex: 1;
margin: 0 0.5em;
}
form .input-group-item input.boxinput,textarea {
width: 100%;
box-sizing: border-box;
}
+64 -92
View File
@@ -4,116 +4,88 @@ main {
width: 100vw; width: 100vw;
} }
.serviceWrapper {
width: 80%; .serviceGrid {
display: grid; display: grid;
grid-template-columns: 1fr 1fr; grid-template-columns: repeat(auto-fill, minmax(280px, 1fr));
grid-gap: 1em; gap: 1.5rem;
padding: 2rem;
margin: auto auto; margin: 50px 2%;
margin-top: 4em;
} }
.categoryContainer { /* Base styles for all cards */
border: 4px solid #002244; .baseServiceCard {
border-radius: 5px;
box-shadow : 0 0 20px #002244;
margin-bottom: 20px;
}
.categoryLabel {
padding-top: 5px;
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; display: flex;
flex-direction: row; gap: 0.6rem;
padding: 1rem;
border-radius: 14px;
box-shadow: 0 8px 8px rgba(0, 0, 0, 0.3);
} }
/* Category Title Card Styling */
.categoryTitleCard {
align-items: center;
justify-content: center;
text-align: center;
box-shadow: none;
min-height: 140px;
}
.categoryTitle {
margin: 0;
font-weight: bold;
font-size: 1.5rem;
}
/* Service Card Styling */
.serviceCard {
display: flex;
gap: 0.6rem;
padding: 1rem;
border-radius: 14px;
height: fit-content;
width: fit-content;
}
/*.serviceCard:hover {
transform: translateY(-4px);
box-shadow: 0 12px 30px rgba(0, 0, 0, 0.12);
}*/
.serviceContent { .serviceContent {
flex-grow: 1; flex: 1;
margin-right: 4%;
} }
.serviceTitle { .serviceTitle {
margin: 0.2em !important; margin: 0 0 0.5rem;
font-size: 1.2rem;
} }
.serviceDescription { .serviceDescription {
margin-top: 0px !important; margin: 0 0 1rem;
font-size: 0.95rem;
line-height: 1.5;
} }
.serviceDescription::before { .serviceLink a {
content: " - "; color: #0066cc;
font-size: 18px; text-decoration: none;
display: inline; font-weight: 600;
} }
.serviceLink { .serviceLink a:hover {
width: 70%; text-decoration: underline;
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 { .serviceImage {
flex-shrink: 1; width: 56px;
width: 100px; height: 56px;
height: 100px; object-fit: contain;
align-self: flex-start;
margin: auto auto;
}
@media (max-width: 800px) {
.serviceWrapper {
grid-template-columns: 1fr;
}
.categoryContainer {
width: 100%;
}
}
@media (max-width: 480px) {
.categoryContainer {
border-radius: unset;
border: unset;
box-shadow: unset;
margin-bottom: unset;
}
.serviceWrapper {
width: 100%;
}
.serviceImage {
width: 25%;
height: auto;
}
.serviceContent {
width: 50%;
}
}
@media (max-width: 360px) {
.serviceContent {
font-size: 14px;
}
} }
+5 -8
View File
@@ -58,21 +58,18 @@ require_once dirname(__DIR__, 2) . implode(\DIRECTORY_SEPARATOR, ['', 'inc', 'in
<script <script
src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js" src="https://cdn.jsdelivr.net/npm/chart.js@4.5.1/dist/chart.umd.min.js"
integrity="sha512-WoViKhKD4qI2WruSZqv9+kvM4WfFhUMQCLN4QlDTt5aU56fLQy2gYoxWIqlEnXqJy/+Ac5q/hk1oWfqnMDhwMA==" integrity="sha384-jb8JQMbMoBUzgWatfe6COACi2ljcDdZQ2OxczGA3bGNeWe+6DChMTBJemed7ZnvJ"
crossorigin="anonymous" crossorigin="anonymous"
referrerpolicy="no-referrer"
></script> ></script>
<script <script
src="https://cdn.jsdelivr.net/npm/date-fns@4.4.0/cdn.min.js" src="https://cdn.jsdelivr.net/npm/moment@2.30.1/moment.min.js"
integrity="sha512-mA7EWmvK4CWPMTbkqGfSNZBMdN9F8+wQGlUqlOxSKv1tJeDKblnuZa7bJkobcg3cnCQ+BrZGX3uenWCFq6cmEA==" integrity="sha384-+EEFFjsGn4BnW70Nv0OvoMe1VZuqS4xvx90V2MTeuYUUZSEabg7FSMWl6s2DJTAO"
crossorigin="anonymous" crossorigin="anonymous"
referrerpolicy="no-referrer"
></script> ></script>
<script <script
src="https://cdn.jsdelivr.net/npm/chartjs-adapter-date-fns@3.0.0/dist/chartjs-adapter-date-fns.bundle.min.js" src="https://cdn.jsdelivr.net/npm/chartjs-adapter-moment@1.0.1/dist/chartjs-adapter-moment.min.js"
integrity="sha512-VPUN3sK5Jce8lVuVWfTZolO+BDodUHFq1QsNHmszMbKpYrQzjCxvC0FDG7igWCYBcsFDpqhcVq4sQ851OqhAPg==" integrity="sha384-s5cwu7c1MxOfC90RGRDWeB53/7VpDTxXi0YxKJF5y9oKA99+UYxMk0qvlqso188s"
crossorigin="anonymous" crossorigin="anonymous"
referrerpolicy="no-referrer"
></script> ></script>
<script> <script>
+166 -35
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">
@@ -63,32 +70,156 @@ if ($new == 0) {
<body> <body>
<nav> <nav>
<?php echo navbar(1, 'prosjekt'); ?> <?php echo navbar(1, 'prosjekt'); ?>
<?php echo loginbar(null, $pdo); ?> <?php echo loginbar(null, $pdo); ?>
</nav> </nav>
<main> <main>
<h2>Nytt prosjekt</h2> <h2>Nytt prosjekt</h2>
<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> <div class="input-group">
<p class="subnote no-chin">Hva går prosjektet ditt ut på?</p> <div class="input-group-item">
<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="subtitle no-chin">Beskrivelse (<i style="opacity:0.5;">markdown</i>)</p>
<textarea class="tall" name="desc" style="width:100%" rows="8" class="boxinput"><?php echo implode("\n", $project->getDescription()); ?></textarea> <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>
<textarea name="desc_no" rows="3" class="boxinput" required><?php echo implode("\n", $project->getDescriptionNo()); ?></textarea>
</div>
<?php echo '<input type="hidden" name="id" value="' . $project->getID() . '" />'; ?> <div class="input-group-item">
<input type="hidden" name="active" value="1"/> <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>
<br>
<textarea name="desc_en" rows="3" class="boxinput" required><?php echo implode("\n", $project->getDescriptionEn()); ?></textarea>
</div>
</div>
<div style="margin-top: 0.2em;"> <div class="input-group">
<hr class="ruler"> <div class="input-group-item">
<input type="submit" class="btn" value="<?php echo $new ? 'Opprett prosjekt' : 'Lagre endringer'; ?>"></input> <p class="subtitle no-chin">Gitea-link</p>
<?php if (!$new) {?><input type="submit" class="btn" name="delete" value="Slett"></input><?php } ?> <p class="subnote">Link til prosjektet på Gitea</p>
</div> <input
</form> type="text"
</main> name="gitea"
placeholder="https://git.pvv.ntnu.no/Projects/mittprosjekt"
value="<?php echo $project->getGiteaLink(); ?>"
class="boxinput"
>
</div>
<div class="input-group-item">
<p class="subtitle no-chin">Issue board-link</p>
<p class="subnote">Link til issue board på Gitea</p>
<input
type="text"
name="issue"
placeholder="https://git.pvv.ntnu.no/Projects/mittprosjekt/issues"
value="<?php echo $project->getIssueBoardLink(); ?>"
class="boxinput"
>
</div>
</div>
<div class="input-group">
<div class="input-group-item">
<p class="subtitle no-chin">Logo-URL</p>
<p class="subnote">Link til logo for prosjektet</p>
<input
type="text"
name="logo"
placeholder="https://www.pvv.ntnu.no/~user/pictures/logos/prosjektlogo.png"
value="<?php echo $project->getLogoURL(); ?>"
class="boxinput"
>
</div>
<div class="input-group-item">
<p class="subtitle no-chin">Wiki-link</p>
<p class="subnote">Link til wiki-side</p>
<input
type="text"
name="wiki"
placeholder="https://wiki.pvv.ntnu.no/wiki/Prosjekter/Mitt_Prosjekt"
value="<?php echo $project->getWikiLink(); ?>"
class="boxinput"
>
</div>
</div>
<div class="input-group">
<div class="input-group-item">
<p class="subtitle no-chin">Programmeringsspråk</p>
<p class="subnote">Hvilke programmeringsspråk brukes i prosjektet?</p>
<input
type="text"
name="programming-languages"
placeholder="php,javascript,html,css"
value="<?php echo implode("\n", $project->getProgrammingLanguages()); ?>"
class="boxinput"
>
</div>
<div class="input-group-item">
<p class="subtitle no-chin">Teknologier</p>
<p class="subnote">Hvilke teknologier brukes i prosjektet?</p>
<input
type="text"
name="technologies"
placeholder="mysql,rest,ajax"
value="<?php echo implode("\n", $project->getTechnologies()); ?>"
class="boxinput"
>
</div>
<div class="input-group-item">
<p class="subtitle no-chin">Nøkkelord</p>
<p class="subnote">Nøkkelord som beskriver prosjektet</p>
<input
type="text"
name="keywords"
placeholder="web,very-cool"
value="<?php echo implode("\n", $project->getKeywords()); ?>"
class="boxinput"
>
</div>
</div>
<div class="input-group">
<div class="input-group-item">
<p class="subtitle no-chin">Lisens</p>
<p class="subnote">Hvilken lisens bruker prosjektet?</p>
<input
type="text"
name="license"
placeholder="GPL-3.0"
value="<?php echo $project->getLicense(); ?>"
class="boxinput"
>
</div>
<div class="input-group-item">
<p class="subtitle no-chin">Skult</p>
<p class="subnote">Skal prosjektet være skjult fra prosjektindeksen?</p>
<input
type="checkbox"
name="is_hidden"
value="<?php echo $project->isHidden(); ?>"
>
</div>
</div>
<?php echo '<input type="hidden" name="id" value="' . $project->getID() . '" />'; ?>
<input type="hidden" name="active" value="1"/>
<div style="margin-top: 0.2em;">
<hr class="ruler">
<input type="submit" class="btn" value="<?php echo $project_is_new ? 'Opprett prosjekt' : 'Lagre endringer'; ?>"></input>
<?php if (!$project_is_new) {?><input type="submit" class="btn" name="delete" value="Slett"></input><?php } ?>
</div>
</form>
</main>
</body> </body>
+58 -13
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,25 +83,71 @@ $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];
} }
foreach ($randProjects as $i) { foreach ($randProjects as $i) {
$project = $projects[$i]; $project = $projects[$i];
$owner = $projectManager->getProjectOwner($project->getID()); $organizers = $projectManager->getProjectOrganizers($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(); ?>">
<div class="card-content"> <article class="project-card">
<h4 class="project-title"><?php echo $project->getName(); ?></h4>
<?php <header class="project-header">
$Parsedown = new Parsedown(); <?php if (!empty($project->getLogoURL())): ?>
echo $Parsedown->text(implode("\n", array_slice($project->getDescription(), 0, 2))); <img src="<?php echo htmlspecialchars($project->getLogoURL()); ?>"
?> alt=""
</div> class="project-logo">
<p class="project-organizer">Organisert av <?php echo $owner['name']; ?></p> <?php endif; ?>
</div></a>
<h4 class="project-title">
<?php echo htmlspecialchars($project->getTitle()); ?>
</h4>
</header>
<div class="card-content">
<p class="project-description">
<?php
$Parsedown = new Parsedown();
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>
<?php endif; ?>
</div>
<footer class="project-footer">
<span class="project-organizer">
Organisert av <?php echo htmlspecialchars(implode(', ', array_map(function ($org) {
return $org->getName();
}, $organizers))); ?>
</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>
+3 -3
View File
@@ -20,7 +20,7 @@ if (!$project) {
exit; exit;
} }
$members = $projectManager->getProjectMembers($projectID); $members = $projectManager->getProjectMaintainers($projectID);
$normal_members = $members; $normal_members = $members;
foreach ($normal_members as $i => $data) { foreach ($normal_members as $i => $data) {
if ($data['lead']) { if ($data['lead']) {
@@ -65,10 +65,10 @@ if ($attrs) {
<main class="contentsplit"> <main class="contentsplit">
<div class="gridr"> <div class="gridr">
<h2><?php echo $project->getName(); ?></h2> <h2><?php echo $project->getTitle(); ?></h2>
<?php <?php
$Parsedown = new Parsedown(); $Parsedown = new Parsedown();
echo $Parsedown->text(implode("\n", $project->getDescription())); echo $Parsedown->text(implode("\n", $project->getDescriptionEn()));
?> ?>
</div> </div>
-120
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>
+131 -28
View File
@@ -6,9 +6,25 @@ 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 = [
header('Location: ' . $_SERVER['HTTP_REFERER']); 'title',
exit; 'desc_no',
'desc_en',
'gitea',
'issue',
'wiki',
'programming-languages',
'technologies',
'keywords',
'license',
'logo'
];
foreach ($required_fields as $field) {
if (!isset($_POST[$field])) {
header('Location: ' . $_SERVER['HTTP_REFERER']);
exit;
}
} }
require_once __DIR__ . '/../../vendor/simplesamlphp/simplesamlphp/lib/_autoload.php'; require_once __DIR__ . '/../../vendor/simplesamlphp/simplesamlphp/lib/_autoload.php';
@@ -16,41 +32,114 @@ $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']; function clean_tags(string $raw): string {
$tags = array_map('trim', explode(',', $raw));
$tags = array_filter($tags, fn($tag) => !empty($tag));
return implode(',', $tags);
}
$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 = clean_tags($_POST['programming-languages']);
$techs = clean_tags($_POST['technologies']);
$keywords = clean_tags($_POST['keywords']);
$license = $_POST['license'];
$logo = $_POST['logo'];
$is_hidden = isset($_POST['is_hidden']) ? 1 : 0;
$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,
programming_languages,
technologies,
keywords,
license,
logo_url,
is_hidden
)
VALUES
(
:title,
:desc_no,
:desc_en,
:gitea,
:issue,
:wiki,
:programming_languages,
:technologies,
:keywords,
:license,
:logo,
:is_hidden
)
END;
$statement = $pdo->prepare($query); $statement = $pdo->prepare($query);
$statement->bindValue(':title', $title, PDO::PARAM_STR); $statement->bindValue(':title', $title, PDO::PARAM_STR);
$statement->bindValue(':desc', $desc, PDO::PARAM_STR); $statement->bindValue(':desc_no', $desc_no, PDO::PARAM_STR);
$statement->bindValue(':desc_en', $desc_en, PDO::PARAM_STR);
$statement->bindValue(':gitea', $gitea, PDO::PARAM_STR);
$statement->bindValue(':issue', $issue, PDO::PARAM_STR);
$statement->bindValue(':wiki', $wiki, PDO::PARAM_STR);
$statement->bindValue(':programming_languages', $langs, PDO::PARAM_STR);
$statement->bindValue(':technologies', $techs, PDO::PARAM_STR);
$statement->bindValue(':keywords', $keywords, PDO::PARAM_STR);
$statement->bindValue(':license', $license, PDO::PARAM_STR);
$statement->bindValue(':logo', $logo, PDO::PARAM_STR);
$statement->bindValue(':is_hidden', $is_hidden, PDO::PARAM_BOOL);
$statement->execute(); $statement->execute();
$new_id = $pdo->lastInsertId(); $new_project_id = $pdo->lastInsertId();
$ownerQuery = "INSERT INTO projectmembers (projectid, name, uname, mail, role, lead, owner) VALUES (:id, :owner, :owneruname, :owneremail, 'Prosjektleder', TRUE, TRUE)"; $insertOrganizerQuery = <<<END
$statement = $pdo->prepare($ownerQuery); INSERT INTO
$statement->bindValue(':id', $new_id, PDO::PARAM_STR); project_maintainer (
$statement->bindValue(':owner', $name, PDO::PARAM_STR); uname,
$statement->bindValue(':owneruname', $uname, PDO::PARAM_STR); project_id,
$statement->bindValue(':owneremail', $mail, PDO::PARAM_STR); name,
email,
is_organizer
)
VALUES
(
:username,
:project_id,
:user_real_name,
:user_email,
TRUE
)
END;
$statement = $pdo->prepare($insertOrganizerQuery);
$statement->bindValue(':username', $uname, PDO::PARAM_STR);
$statement->bindValue(':project_id', $new_project_id, PDO::PARAM_INT);
$statement->bindValue(':user_real_name', $name, PDO::PARAM_STR);
$statement->bindValue(':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->getProjectMaintainers($id);
// if ($do_join_or_leave and $owner['uname'] != $uname) { // if ($do_join_or_leave and $owner['uname'] != $uname) {
if ($do_join_or_leave) { if ($do_join_or_leave) {
@@ -62,7 +151,12 @@ if ($id == 0) {
} }
} }
if ($is_member) {// leave if ($is_member) {// leave
$query = 'DELETE FROM projectmembers WHERE projectid=:id AND uname=:uname and lead=FALSE and owner=FALSE;'; $query = '
DELETE FROM projectmembers
WHERE
projectid = :id
AND uname = :uname
';
$statement = $pdo->prepare($query); $statement = $pdo->prepare($query);
$statement->bindValue(':id', $id, PDO::PARAM_STR); $statement->bindValue(':id', $id, PDO::PARAM_STR);
$statement->bindValue(':uname', $uname, PDO::PARAM_STR); $statement->bindValue(':uname', $uname, PDO::PARAM_STR);
@@ -70,7 +164,12 @@ if ($id == 0) {
$statement->execute(); $statement->execute();
echo 'leave'; echo 'leave';
} else {// join } else {// join
$query = "INSERT INTO projectmembers (projectid, name, uname, mail, role, lead, owner) VALUES (:id, :name, :uname, :mail, 'Medlem', FALSE, FALSE)"; $query = '
INSERT INTO
projectmembers(projectid, name, uname, mail, role)
VALUES
(:id, :name, :uname, :mail, \'Medlem\')
';
$statement = $pdo->prepare($query); $statement = $pdo->prepare($query);
$statement->bindValue(':id', $id, PDO::PARAM_STR); $statement->bindValue(':id', $id, PDO::PARAM_STR);
$statement->bindValue(':name', $name, PDO::PARAM_STR); $statement->bindValue(':name', $name, PDO::PARAM_STR);
@@ -94,19 +193,23 @@ if ($id == 0) {
// this should be done as a transaction... // this should be done as a transaction...
$pdo->beginTransaction(); $pdo->beginTransaction();
// NOTE: project members are deleted via ON DELETE CASCADE
$query = 'DELETE FROM projects WHERE id=:id'; $query = 'DELETE FROM projects WHERE id=:id';
$statement = $pdo->prepare($query); $statement = $pdo->prepare($query);
$statement->bindValue(':id', $id, PDO::PARAM_INT); $statement->bindValue(':id', $id, PDO::PARAM_INT);
$statement->execute(); $statement->execute();
$query = 'DELETE FROM projectmembers WHERE projectid=:id';
$statement = $pdo->prepare($query);
$statement->bindValue(':id', $id, PDO::PARAM_INT);
$statement->execute();
$pdo->commit(); $pdo->commit();
} else { } else {
$query = 'UPDATE projects SET name=:title, description=:desc WHERE id=:id'; $query = '
UPDATE
projects
SET
name = :title,
description = :desc
WHERE
id = :id
';
$statement = $pdo->prepare($query); $statement = $pdo->prepare($query);
$statement->bindValue(':title', $title, PDO::PARAM_STR); $statement->bindValue(':title', $title, PDO::PARAM_STR);
+189 -37
View File
@@ -4,13 +4,139 @@ namespace pvv\side;
require_once \dirname(__DIR__, 2) . implode(\DIRECTORY_SEPARATOR, ['', 'inc', 'include.php']); require_once \dirname(__DIR__, 2) . implode(\DIRECTORY_SEPARATOR, ['', 'inc', 'include.php']);
$colorPalette = [
'#FFB3BA',
'#FFCFAA',
'#FFFFBA',
'#BAFFC9',
'#BAE1FF',
'#E2BAFF',
];
function rgbToHsl(int $r, int $g, int $b): array
{
// Assert valid RGB range
if ($r < 0 || $r > 255 || $g < 0 || $g > 255 || $b < 0 || $b > 255) {
throw new \InvalidArgumentException('RGB values must be between 0 and 255');
}
$r /= 255;
$g /= 255;
$b /= 255;
$max = max($r, $g, $b);
$min = min($r, $g, $b);
$delta = $max - $min;
$l = ($max + $min) / 2;
if ($delta == 0) {
$h = 0;
$s = 0;
} else {
$s = $delta / (1 - abs(2 * $l - 1));
if ($max === $r) {
$h = 60 * (($g - $b) / $delta);
if ($h < 0) {
$h += 360;
}
} elseif ($max === $g) {
$h = 60 * ((($b - $r) / $delta) + 2);
} else {
$h = 60 * ((($r - $g) / $delta) + 4);
}
}
return [
'h' => round($h, 2),
's' => round($s * 100, 2),
'l' => round($l * 100, 2),
];
}
function hslToRgb(float $h, float $s, float $l): array
{
// Assert valid HSL ranges
if ($h < 0 || $h > 360) {
throw new \InvalidArgumentException('Hue must be between 0 and 360');
}
if ($s < 0 || $s > 100 || $l < 0 || $l > 100) {
throw new \InvalidArgumentException('Saturation and Lightness must be between 0 and 100');
}
$s /= 100;
$l /= 100;
$c = (1 - abs(2 * $l - 1)) * $s;
$m = $l - $c / 2;
// Determine hue sector explicitly
if ($h < 60) {
$r1 = $c;
$g1 = ($h / 60) * $c;
$b1 = 0;
} elseif ($h < 120) {
$r1 = (2 - $h / 60) * $c;
$g1 = $c;
$b1 = 0;
} elseif ($h < 180) {
$r1 = 0;
$g1 = $c;
$b1 = (($h - 120) / 60) * $c;
} elseif ($h < 240) {
$r1 = 0;
$g1 = (4 - $h / 60) * $c;
$b1 = $c;
} elseif ($h < 300) {
$r1 = (($h - 240) / 60) * $c;
$g1 = 0;
$b1 = $c;
} else { // h < 360
$r1 = $c;
$g1 = 0;
$b1 = (6 - $h / 60) * $c;
}
return [
'r' => (int) round(($r1 + $m) * 255),
'g' => (int) round(($g1 + $m) * 255),
'b' => (int) round(($b1 + $m) * 255),
];
}
function generateHighlightColor(string $hexColor): string {
$r = hexdec(substr($hexColor, 1, 2));
$g = hexdec(substr($hexColor, 3, 2));
$b = hexdec(substr($hexColor, 5, 2));
$a = hexdec(substr($hexColor, 7, 2));
if (!$a) {
$a = 255;
}
$hsl = rgbToHsl($r, $g, $b);
// Increase lightness by 8%, cap at 100%
$hsl['l'] = min(100, $hsl['l'] + 8);
$rgb = hslToRgb($hsl['h'], $hsl['s'], $hsl['l']);
return sprintf(
"#%02x%02x%02x%02x",
$rgb['r'],
$rgb['g'],
$rgb['b'],
$a,
);
}
$services = [ $services = [
"vcs" => [ "vcs" => [
"title" => "Versjonskontroll og utvikling", "title" => "Versjonskontroll og utvikling",
"services" => [ "services" => [
[ [
"name" => "Gitea", "name" => "Gitea",
"description" => "Vår interne git-tjener, åpen for alle medlemmer. Kommer med CI/CD, nettside-artefakter, pakke-register og mye mer.", "description" => "Vår interne git-tjener, åpen for alle medlemmer. Kommer med CI/CD, nettside-artifakter, pakke-register og mye mer.",
"link" => "https://git.pvv.ntnu.no", "link" => "https://git.pvv.ntnu.no",
"link_text" => "Gå til git.pvv.ntnu.no", "link_text" => "Gå til git.pvv.ntnu.no",
"image" => "img/gitea.svg", "image" => "img/gitea.svg",
@@ -76,7 +202,7 @@ $services = [
], ],
[ [
"name" => "Discord", "name" => "Discord",
"description" => "Vår hovedkanal, her finner du alt fra offisielle announcements til memes og driftsdiskusjoner.", "description" => "Vår hovedkanal, her finner du alt fra ofisielle announcements til memes og driftsdiskusjoner.",
"link" => "https://discord.gg/WpaHGV8K", "link" => "https://discord.gg/WpaHGV8K",
"link_text" => "Gå til Discord", "link_text" => "Gå til Discord",
"image" => "img/discord.svg", "image" => "img/discord.svg",
@@ -163,7 +289,7 @@ $services = [
], ],
[ [
"name" => "Dørbjelle", "name" => "Dørbjelle",
"description" => "PVVs dørbjelle er koblet til internett, og lar deg ringe på hvis du spør botten pent på Discord eller Matrix", "description" => "PVVs dørbjelle er koblet til internett, og lar deg ringe på hvis du spør botten pent på Discordh eller Matrix",
"link" => "https://wiki.pvv.ntnu.no/wiki/Tjenester/D%C3%B8rbjelle", "link" => "https://wiki.pvv.ntnu.no/wiki/Tjenester/D%C3%B8rbjelle",
"link_text" => "Se dokumentasjon på wiki", "link_text" => "Se dokumentasjon på wiki",
"image" => "img/doorbell.png", "image" => "img/doorbell.png",
@@ -225,48 +351,74 @@ $services = [
], ],
]; ];
$servicesArrayKeys = array_keys($services);
for ($i = 0; $i < count($services); $i++) {
$servicesKey = $servicesArrayKeys[$i];
$services[$servicesKey]['bgcolor'] = $colorPalette[$i % count($colorPalette)];
}
?> ?>
<!DOCTYPE html> <!DOCTYPE html>
<html lang="no"> <html lang="no">
<head> <head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8"> <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"> <meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=yes">
<link rel="shortcut icon" href="/favicon.ico"> <link rel="shortcut icon" href="/favicon.ico">
<link rel="stylesheet" href="/css/normalize.css"> <link rel="stylesheet" href="/css/normalize.css">
<link rel="stylesheet" href="/css/style.css"> <link rel="stylesheet" href="/css/style.css">
<link rel="stylesheet" href="/css/services.css"> <link rel="stylesheet" href="/css/services.css">
<meta name="theme-color" content="#024" /> <meta name="theme-color" content="#024" />
<title>Tjenesteverkstedet</title> <title>Tjenesteverkstedet</title>
</head> <style>
<?php foreach ($services as $categoryId => $category):
$categoryClass = '.category-' . htmlspecialchars($categoryId);
?>
<?php echo $categoryClass; ?> {
background: linear-gradient(135deg, <?php echo generateHighlightColor($category['bgcolor']) ?>, <?php echo $category['bgcolor']; ?>);
}
<?php endforeach; ?>
</style>
</head>
<body> <header>Tjenesteverkstedet</header>
<header>Tjenesteverkstedet</header>
<nav> <body>
<?php echo navbar(1, 'tjenester'); ?> <nav>
<?php echo loginbar($sp, $pdo); ?> <?php echo navbar(1, 'tjenester'); ?>
</nav> <?php echo loginbar($sp, $pdo); ?>
</nav>
<main>
<div class="serviceGrid">
<?php foreach ($services as $categoryId => $category):
$categoryClass = 'category-' . htmlspecialchars($categoryId);
?>
<main> <div class="baseServiceCard categoryTitleCard <?php echo $categoryClass; ?>">
<div class="serviceWrapper"> <h3 class="categoryTitle">
<?php foreach ($services as $categoryName => $category): ?> <?php echo htmlspecialchars($category['title']); ?>
<div class="categoryContainer"> </h3>
<div class="categoryLabel"><?php echo htmlspecialchars($category['title']); ?></div> </div>
<div class="categoryContent">
<?php foreach ($category['services'] as $service): ?> <?php foreach ($category['services'] as $service): ?>
<div class="service"> <div class="baseServiceCard serviceCard <?php echo $categoryClass; ?>">
<div class="serviceContent"> <div class="serviceContent">
<h2 class="serviceTitle"><?php echo htmlspecialchars($service['name']); ?></h2> <h3 class="serviceTitle"><?php echo htmlspecialchars($service['name']); ?></h3>
<p class="serviceDescription"><?php echo htmlspecialchars($service['description']); ?></p> <p class="serviceDescription"><?php echo htmlspecialchars($service['description']); ?></p>
<div class="serviceLink"><a href="<?php echo htmlspecialchars($service['link']); ?>" target="_blank"><?php echo htmlspecialchars($service['link_text']); ?></a></div> <div class="serviceLink">
</div> <a href="<?php echo htmlspecialchars($service['link']); ?>" target="_blank">
<img class="serviceImage" src="<?php echo htmlspecialchars($service['image']); ?>" alt="<?php echo htmlspecialchars($service['name']); ?>-logo"> <?php echo htmlspecialchars($service['link_text']); ?>
</a>
</div> </div>
<?php endforeach; ?>
</div> </div>
<img class="serviceImage"
src="<?php echo htmlspecialchars($service['image']); ?>"
alt="<?php echo htmlspecialchars($service['name']); ?> logo">
</div> </div>
<?php endforeach; ?> <?php endforeach; ?>
</div> <?php endforeach; ?>
</main> </div>
</body> </main>
</body>
</html> </html>