From d763c4344c86f6c0296b9824c1a27adc56c17524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?P=C5=91cze=20Bence?= Date: Sun, 16 Apr 2023 03:31:40 +0200 Subject: [PATCH] implement community basics --- .../structure/20230412_1955_communities.sql | 20 ++ public/static/css/rvr.css | 48 +++- .../js/communities/community_members.js | 62 +++++ public/static/js/rvr.js | 8 + public/static/package-lock.json | 57 +++++ public/static/package.json | 3 +- src/Controller/CommunityController.php | 216 ++++++++++++++++++ src/Controller/HomeController.php | 27 ++- src/Controller/UserSearchController.php | 42 ++++ src/PersistentData/Model/Community.php | 57 +++++ src/PersistentData/Model/CommunityMember.php | 72 ++++++ src/PersistentData/Model/User.php | 5 + src/Repository/CommunityMemberRepository.php | 48 ++++ src/Repository/CommunityRepository.php | 19 ++ src/Repository/UserRepository.php | 11 + views/communities/community.php | 50 ++++ views/communities/community_edit.php | 20 ++ views/communities/community_members.php | 42 ++++ views/home.php | 28 +++ views/index.php | 8 - web.php | 16 +- 21 files changed, 844 insertions(+), 15 deletions(-) create mode 100644 database/migrations/structure/20230412_1955_communities.sql create mode 100644 public/static/js/communities/community_members.js create mode 100644 public/static/package-lock.json create mode 100644 src/Controller/CommunityController.php create mode 100644 src/Controller/UserSearchController.php create mode 100644 src/PersistentData/Model/Community.php create mode 100644 src/PersistentData/Model/CommunityMember.php create mode 100644 src/Repository/CommunityMemberRepository.php create mode 100644 src/Repository/CommunityRepository.php create mode 100644 views/communities/community.php create mode 100644 views/communities/community_edit.php create mode 100644 views/communities/community_members.php create mode 100644 views/home.php delete mode 100644 views/index.php diff --git a/database/migrations/structure/20230412_1955_communities.sql b/database/migrations/structure/20230412_1955_communities.sql new file mode 100644 index 0000000..b926c96 --- /dev/null +++ b/database/migrations/structure/20230412_1955_communities.sql @@ -0,0 +1,20 @@ +CREATE TABLE `communities` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `name` varchar(255) NOT NULL, + `currency` varchar(3) NOT NULL, + `created` timestamp NOT NULL DEFAULT current_timestamp(), + PRIMARY KEY (`id`), +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; + +CREATE TABLE `community_members` ( + `id` int(10) unsigned NOT NULL AUTO_INCREMENT, + `community_id` int(10) unsigned NOT NULL, + `user_id` int(10) unsigned DEFAULT NULL, + `owner` tinyint(1) NOT NULL DEFAULT 0, + PRIMARY KEY (`id`), + UNIQUE KEY `unique_user_for_community` (`community_id`, `user_id`), + KEY `community_id` (`community_id`), + KEY `user_id` (`user_id`), + CONSTRAINT `community_members_community_id` FOREIGN KEY (`community_id`) REFERENCES `communities` (`id`), + CONSTRAINT `community_members_user_id` FOREIGN KEY (`user_id`) REFERENCES `users` (`id`) +) ENGINE = InnoDB DEFAULT CHARSET = utf8mb4; diff --git a/public/static/css/rvr.css b/public/static/css/rvr.css index 9608d75..9ea08df 100644 --- a/public/static/css/rvr.css +++ b/public/static/css/rvr.css @@ -88,10 +88,14 @@ sub { } hr { - border: solid #bbbbbb 1px; + border: solid #bbbbcc 1px; margin: 10px 0; } +.normal { + font-weight: 400; +} + .bold { font-weight: 700; } @@ -418,13 +422,53 @@ div.buttonContainer>button { div.box { width: 576px; - background-color: #eeeeee; + background-color: #eeeef4; border-radius: 3px; margin: 10px auto; padding: 10px; box-sizing: border-box; } +div.gridContainer { + display: grid; + grid-template-columns: repeat(auto-fit, minmax(400px, 1fr)); + grid-gap: 10px; +} + +div.gridContainer > div { + background-color: #eeeef4; + border-radius: 3px; + padding: 5px 10px; +} + +table { + border-collapse: separate; + border-spacing: 0; +} + +table.fullWidth { + width: 100%; +} + +table th { + font-weight: bold; +} + +table th, table td { + padding: 2px 0; + vertical-align: middle; +} + +.choices__inner { + box-sizing: border-box; +} + +@media screen and (max-width: 424px) { + div.gridContainer { + grid-template-columns: auto; + } +} + @media screen and (max-width: 599px) { header h1 span { display: none; diff --git a/public/static/js/communities/community_members.js b/public/static/js/communities/community_members.js new file mode 100644 index 0000000..6a3ecd2 --- /dev/null +++ b/public/static/js/communities/community_members.js @@ -0,0 +1,62 @@ +(function () { + const element = document.getElementById('new_member_user_id'); + const choices = new Choices(element, { + noResultsText: 'No users found', + noChoicesText: 'Start typing to search users' + }); + + element.addEventListener('search', RVR.debounce(async function (e) { + RVR.httpRequest('GET', searchUserUrl.replace('QUERY', encodeURIComponent(e.detail.value)), function () { + choices.setChoices(this.response.results, 'value', 'label', true); + }); + })); + + element.addEventListener('choice', function () { + choices.setChoices([], 'value', 'label', true); + document.getElementById('new_member_button').disabled = false; + }); + + document.getElementById('new_member_button').addEventListener('click', function () { + document.getElementById('loading').style.visibility = 'visible'; + + let data = new FormData(); + data.append('user_id', document.getElementById('new_member_user_id').value); + + RVR.httpRequest('POST', newMemberUrl, function () { + window.location.reload(); + }, data); + }); + + const ownerCheckboxesButtons = document.getElementsByClassName('member_owner'); + for (const ownerCheckboxesButton of ownerCheckboxesButtons) { + ownerCheckboxesButton.addEventListener('change', function () { + document.getElementById('loading').style.visibility = 'visible'; + + let data = new FormData(); + data.append('community_member_id', this.dataset.id); + data.append('owner', this.checked ? 1 : 0); + + RVR.httpRequest('POST', editMemberUrl, function () { + document.getElementById('loading').style.visibility = 'hidden'; + + if (!this.response.success) { + ownerCheckboxesButton.checked = !ownerCheckboxesButton.checked; + } + }, data); + }); + }; + + const deleteButtons = document.getElementsByClassName('delete_member'); + for (const deleteButton of deleteButtons) { + deleteButton.addEventListener('click', function () { + document.getElementById('loading').style.visibility = 'visible'; + + let data = new FormData(); + data.append('community_member_id', this.dataset.id); + + RVR.httpRequest('POST', deleteMemberUrl, function () { + window.location.reload(); + }, data); + }); + }; +})(); diff --git a/public/static/js/rvr.js b/public/static/js/rvr.js index ed2ef94..d8bc101 100644 --- a/public/static/js/rvr.js +++ b/public/static/js/rvr.js @@ -193,6 +193,14 @@ var RVR = { form.onreset = function () { form.elements.submit.disabled = true; } + }, + + debounce: function(func, timeout = 300) { + let timer; + return (...args) => { + clearTimeout(timer); + timer = setTimeout(() => { func.apply(this, args); }, timeout); + }; } }; diff --git a/public/static/package-lock.json b/public/static/package-lock.json new file mode 100644 index 0000000..f1ac542 --- /dev/null +++ b/public/static/package-lock.json @@ -0,0 +1,57 @@ +{ + "requires": true, + "lockfileVersion": 1, + "dependencies": { + "@babel/runtime": { + "version": "7.21.0", + "resolved": "https://registry.npmjs.org/@babel/runtime/-/runtime-7.21.0.tgz", + "integrity": "sha512-xwII0//EObnq89Ji5AKYQaRYiW/nZ3llSv29d49IuxPhKbtJoLP+9QUUZ4nVragQVtaVGeZrpB+ZtG/Pdy/POw==", + "requires": { + "regenerator-runtime": "^0.13.11" + } + }, + "choices.js": { + "version": "10.2.0", + "resolved": "https://registry.npmjs.org/choices.js/-/choices.js-10.2.0.tgz", + "integrity": "sha512-8PKy6wq7BMjNwDTZwr3+Zry6G2+opJaAJDDA/j3yxvqSCnvkKe7ZIFfIyOhoc7htIWFhsfzF9tJpGUATcpUtPg==", + "requires": { + "deepmerge": "^4.2.2", + "fuse.js": "^6.6.2", + "redux": "^4.2.0" + } + }, + "deepmerge": { + "version": "4.3.1", + "resolved": "https://registry.npmjs.org/deepmerge/-/deepmerge-4.3.1.tgz", + "integrity": "sha512-3sUqbMEc77XqpdNO7FRyRog+eW3ph+GYCbj+rK+uYyRMuwsVy0rMiVtPn+QJlKFvWP/1PYpapqYn0Me2knFn+A==" + }, + "fuse.js": { + "version": "6.6.2", + "resolved": "https://registry.npmjs.org/fuse.js/-/fuse.js-6.6.2.tgz", + "integrity": "sha512-cJaJkxCCxC8qIIcPBF9yGxY0W/tVZS3uEISDxhYIdtk8OL93pe+6Zj7LjCqVV4dzbqcriOZ+kQ/NE4RXZHsIGA==" + }, + "leaflet": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/leaflet/-/leaflet-1.9.3.tgz", + "integrity": "sha512-iB2cR9vAkDOu5l3HAay2obcUHZ7xwUBBjph8+PGtmW/2lYhbLizWtG7nTeYht36WfOslixQF9D/uSIzhZgGMfQ==" + }, + "leaflet.markercluster": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/leaflet.markercluster/-/leaflet.markercluster-1.5.3.tgz", + "integrity": "sha512-vPTw/Bndq7eQHjLBVlWpnGeLa3t+3zGiuM7fJwCkiMFq+nmRuG3RI3f7f4N4TDX7T4NpbAXpR2+NTRSEGfCSeA==" + }, + "redux": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/redux/-/redux-4.2.1.tgz", + "integrity": "sha512-LAUYz4lc+Do8/g7aeRa8JkyDErK6ekstQaqWQrNRW//MY1TvCEpMtpTWvlQ+FPbWCx+Xixu/6SHt5N0HR+SB4w==", + "requires": { + "@babel/runtime": "^7.9.2" + } + }, + "regenerator-runtime": { + "version": "0.13.11", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.13.11.tgz", + "integrity": "sha512-kY1AZVr2Ra+t+piVaJ4gxaFaReZVH40AKNo7UCX6W+dEwBo/2oZJzqfuN1qLq1oL45o56cPaTXELwrTh8Fpggg==" + } + } +} diff --git a/public/static/package.json b/public/static/package.json index 664c47e..135f4d6 100644 --- a/public/static/package.json +++ b/public/static/package.json @@ -1,6 +1,7 @@ { "dependencies": { "leaflet": "^1.6.0", - "leaflet.markercluster": "^1.4.1" + "leaflet.markercluster": "^1.4.1", + "choices.js": "^10.2.0" } } diff --git a/src/Controller/CommunityController.php b/src/Controller/CommunityController.php new file mode 100644 index 0000000..ff0bddf --- /dev/null +++ b/src/Controller/CommunityController.php @@ -0,0 +1,216 @@ +request = $request; + $this->pdm = new PersistentDataManager(); + $this->userRepository = new UserRepository(); + $this->communityRepository = new CommunityRepository(); + $this->communityMemberRepository = new CommunityMemberRepository(); + } + + public function authorize(): bool + { + return $this->request->user() !== null; + } + + public function getCommunityHome(): ?IContent + { + if (!$this->checkPermission($this->request->query('communityId'), false, $community, $ownCommunityMember)) { + return null; + } + + return new HtmlContent('communities/community', [ + 'community' => $community, + 'members' => $this->getMembers($community), + 'currencyNames' => [], + 'upcomingEvents' => [], + 'editPermission' => $ownCommunityMember->getOwner() + ]); + } + + public function getCommunityNew(): IContent + { + return new HtmlContent('communities/community_edit'); + } + + public function getCommunityEdit(): ?IContent + { + if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { + return null; + } + + return new HtmlContent('communities/community_edit', [ + 'community' => $community + ]); + } + + public function getMembersEdit(): ?IContent + { + if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { + return null; + } + + return new HtmlContent('communities/community_members', [ + 'community' => $community, + 'members' => $this->getMembers($community) + ]); + } + + private function getMembers(Community $community): array + { + $members = iterator_to_array($this->communityMemberRepository->getAllByCommunity($community, true)); + usort($members, function($a, $b) { + return strnatcmp($a->getUser()->getDisplayName(), $b->getUser()->getDisplayName()); + }); + return $members; + } + + + public function newMember(): ?IContent + { + if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { + return null; + } + + $user = $this->userRepository->getById($this->request->post('user_id')); + + $communityMember = new CommunityMember(); + $communityMember->setCommunity($community); + $communityMember->setUser($user); + $this->pdm->saveToDb($communityMember); + + return new JsonContent(['success' => true]); + } + + public function editMember(): ?IContent + { + if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { + return null; + } + + $communityMember = $this->communityMemberRepository->getById($this->request->post('community_member_id')); + if ($communityMember->getUserId() === $this->request->user()->getUniqueId()) { + return new JsonContent([ + 'error' => ['errorText' => 'Own user cannot be edited.'] + ]); + } + + $communityMember->setOwner($this->request->post('owner')); + $this->pdm->saveToDb($communityMember); + + return new JsonContent(['success' => true]); + } + + public function deleteMember(): ?IContent + { + if (!$this->checkPermission($this->request->query('communityId'), true, $community, $ownCommunityMember)) { + return null; + } + + $communityMember = $this->communityMemberRepository->getById($this->request->post('community_member_id')); + if ($communityMember->getUserId() === $this->request->user()->getUniqueId()) { + return new JsonContent([ + 'error' => ['errorText' => 'Own user cannot be deleted.'] + ]); + } + + $this->pdm->deleteFromDb($communityMember); + + return new JsonContent(['success' => true]); + } + + public function saveCommunity(): ?IContent + { + $communityId = $this->request->query('communityId'); + if ($communityId){ + if (!$this->checkPermission($communityId, true, $community, $ownCommunityMember)) { + return null; + } + } else { + $community = new Community(); + } + + $name = $this->request->post('name'); + $currency = $this->request->post('currency'); + if (strlen($name) === 0 || strlen($currency) === 0 || strlen($currency) > 3) { + return new JsonContent([ + 'error' => ['errorText' => 'Please fill all required fields!'] + ]); + } + + $community->setName($name); + $community->setCurrency($currency); + if (!$communityId) { + $community->setCreatedDate(new DateTime()); + } + $this->pdm->saveToDb($community); + + if (!$communityId) { + /** + * @var User $user + */ + $user = $this->request->user(); + + $communityMember = new CommunityMember(); + $communityMember->setCommunity($community); + $communityMember->setUser($user); + $communityMember->setOwner(true); + $this->pdm->saveToDb($communityMember); + } + + return new JsonContent([ + 'redirect' => ['target' => '/' . \Container::$routeCollection->getRoute('community')->generateLink(['communityId' => $community->getId()])] + ]); + } + + private function checkPermission( + int $communityId, + bool $needToBeOwner, + ?Community &$community, + ?CommunityMember &$ownCommunityMember): bool + { + $community = $this->communityRepository->getById($communityId); + if ($community === null) { + return false; + } + + /** + * @var User $user + */ + $user = $this->request->user(); + + $ownCommunityMember = $this->communityMemberRepository->getByCommunityAndUser($community, $user); + if ($ownCommunityMember === null || ($needToBeOwner && !$ownCommunityMember->getOwner())) { + return false; + } + + return true; + } +} diff --git a/src/Controller/HomeController.php b/src/Controller/HomeController.php index cdd10a2..7cec7b6 100644 --- a/src/Controller/HomeController.php +++ b/src/Controller/HomeController.php @@ -1,18 +1,22 @@ request = $request; + $this->communityMemberRepository = new CommunityMemberRepository(); } public function authorize(): bool @@ -20,8 +24,25 @@ class HomeController implements ISecured return $this->request->user() !== null; } - public function getIndex(): IContent + public function getHome(): IContent { - return new HtmlContent('index'); + /** + * @var User $user + */ + $user = $this->request->user(); + + $ownCommunityMembers = $this->communityMemberRepository->getAllByUser($user, true); + $communities = []; + foreach ($ownCommunityMembers as $ownCommunityMember) { + $communities[] = $ownCommunityMember->getCommunity(); + } + usort($communities, function($a, $b) { + return strnatcmp($a->getName(), $b->getName()); + }); + + return new HtmlContent('home', [ + 'communities' => $communities, + 'upcomingEvents' => [] + ]); } } diff --git a/src/Controller/UserSearchController.php b/src/Controller/UserSearchController.php new file mode 100644 index 0000000..fab93f0 --- /dev/null +++ b/src/Controller/UserSearchController.php @@ -0,0 +1,42 @@ +request = $request; + $this->userRepository = new UserRepository(); + } + + public function authorize(): bool + { + return $this->request->user() !== null; + } + + public function searchUser(): IContent + { + $users = iterator_to_array($this->userRepository->searchByName($this->request->query('q'))); + usort($users, function($a, $b) { + return strnatcmp($a->getDisplayName(), $b->getDisplayName()); + }); + + $results = []; + foreach ($users as $user) { + $results[] = ['value' => $user->getId(), 'label' => $user->getFullDisplayName()]; + } + + return new JsonContent([ + 'results' => $results + ]); + } +} diff --git a/src/PersistentData/Model/Community.php b/src/PersistentData/Model/Community.php new file mode 100644 index 0000000..43b057f --- /dev/null +++ b/src/PersistentData/Model/Community.php @@ -0,0 +1,57 @@ +name = $name; + } + + public function setCurrency(string $currency): void + { + $this->currency = $currency; + } + + public function setCreatedDate(DateTime $created): void + { + $this->created = $created; + } + + public function setCreated(string $created): void + { + $this->created = new DateTime($created); + } + + public function getName(): string + { + return $this->name; + } + + public function getCurrency(): string + { + return $this->currency; + } + + public function getCreatedDate(): DateTime + { + return $this->created; + } + + public function getCreated(): string + { + return $this->created->format('Y-m-d H:i:s'); + } +} diff --git a/src/PersistentData/Model/CommunityMember.php b/src/PersistentData/Model/CommunityMember.php new file mode 100644 index 0000000..425834d --- /dev/null +++ b/src/PersistentData/Model/CommunityMember.php @@ -0,0 +1,72 @@ + Community::class, 'user' => User::class]; + + private ?Community $community = null; + + private ?int $communityId = null; + + private ?User $user = null; + + private ?int $userId = null; + + private bool $owner = false; + + public function setCommunity(Community $community): void + { + $this->community = $community; + } + + public function setCommunityId(int $communityId): void + { + $this->communityId = $communityId; + } + + public function setUser(User $user): void + { + $this->user = $user; + } + + public function setUserId(int $userId): void + { + $this->userId = $userId; + } + + public function setOwner(bool $owner): void + { + $this->owner = $owner; + } + + public function getCommunity(): ?Community + { + return $this->community; + } + + public function getCommunityId(): ?int + { + return $this->communityId; + } + + public function getUser(): ?User + { + return $this->user; + } + + public function getUserId(): ?int + { + return $this->userId; + } + + public function getOwner(): bool + { + return $this->owner; + } +} diff --git a/src/PersistentData/Model/User.php b/src/PersistentData/Model/User.php index d0af3a9..d0667de 100644 --- a/src/PersistentData/Model/User.php +++ b/src/PersistentData/Model/User.php @@ -171,6 +171,11 @@ class User extends Model implements IUser return $this->nickname ?: $this->fullName; } + public function getFullDisplayName(): string + { + return $this->nickname ? $this->nickname . ' (' . $this->fullName . ')' : $this->fullName; + } + public function checkPassword(string $password): bool { if ($this->password === null) { diff --git a/src/Repository/CommunityMemberRepository.php b/src/Repository/CommunityMemberRepository.php new file mode 100644 index 0000000..adb2598 --- /dev/null +++ b/src/Repository/CommunityMemberRepository.php @@ -0,0 +1,48 @@ +pdm = new PersistentDataManager(); + } + + public function getById(int $id): ?CommunityMember + { + return $this->pdm->selectFromDbById($id, CommunityMember::class); + } + + public function getAllByCommunity(Community $community, bool $useRelations = false): Generator + { + $select = new Select(\Container::$dbConnection); + $select->where('community_id', '=', $community->getId()); + + yield from $this->pdm->selectMultipleFromDb($select, CommunityMember::class, $useRelations); + } + + public function getAllByUser(User $user, bool $useRelations = false): Generator + { + $select = new Select(\Container::$dbConnection); + $select->where('user_id', '=', $user->getId()); + + yield from $this->pdm->selectMultipleFromDb($select, CommunityMember::class, $useRelations); + } + + public function getByCommunityAndUser(Community $community, User $user) : ?CommunityMember + { + $select = new Select(\Container::$dbConnection); + $select->where('community_id', '=', $community->getId()); + $select->where('user_id', '=', $user->getId()); + + return $this->pdm->selectFromDb($select, CommunityMember::class); + } +} diff --git a/src/Repository/CommunityRepository.php b/src/Repository/CommunityRepository.php new file mode 100644 index 0000000..48bd439 --- /dev/null +++ b/src/Repository/CommunityRepository.php @@ -0,0 +1,19 @@ +pdm = new PersistentDataManager(); + } + + public function getById(int $id): ?Community + { + return $this->pdm->selectFromDbById($id, Community::class); + } +} diff --git a/src/Repository/UserRepository.php b/src/Repository/UserRepository.php index 3882d9d..36d9482 100644 --- a/src/Repository/UserRepository.php +++ b/src/Repository/UserRepository.php @@ -1,5 +1,6 @@ pdm->selectFromDb($select, User::class); } + + public function searchByName(string $name): Generator + { + $select = new Select(\Container::$dbConnection); + $select->where('full_name', 'LIKE', '%' . $name . '%'); + $select->orWhere('nickname', 'LIKE', '%' . $name . '%'); + $select->limit(10); + + yield from $this->pdm->selectMultipleFromDb($select, User::class); + } } diff --git a/views/communities/community.php b/views/communities/community.php new file mode 100644 index 0000000..97f9340 --- /dev/null +++ b/views/communities/community.php @@ -0,0 +1,50 @@ +@extends(templates/layout_normal) + +@section(main) +

getName() ?> [edit]

+ +
+
+

Members

+ +

getUser()->getDisplayName() ?>

+ + +
+

Edit members

+ +
+
+

Currencies

+

Main currency: getCurrency() ?>

+

Further currencies:

+
+
+

Upcoming events

+ 0): ?> + + + + +

There is no upcoming event.

+ +
+
+

Finances

+ + + + + + + + + + + + + +
You owe0 getCurrency() ?>
You're owed0 getCurrency() ?>
Your balance0 getCurrency() ?>
+
+
+@endsection diff --git a/views/communities/community_edit.php b/views/communities/community_edit.php new file mode 100644 index 0000000..2d80483 --- /dev/null +++ b/views/communities/community_edit.php @@ -0,0 +1,20 @@ +@extends(templates/layout_normal) + +@section(main) +

getName() . ' - Edit' : 'New community' ?>

+
+ getRoute('community-edit-action')->generateLink(['communityId' => $community->getId()]) : + Container::$routeCollection->getRoute('community-new-action')->generateLink(); + ?> +
+ + +

+
+ +
+
+
+@endsection diff --git a/views/communities/community_members.php b/views/communities/community_members.php new file mode 100644 index 0000000..5db0fbb --- /dev/null +++ b/views/communities/community_members.php @@ -0,0 +1,42 @@ +@css(node_modules/choices.js/public/assets/styles/choices.min.css) +@js(node_modules/choices.js/public/assets/scripts/choices.js) +@js(js/communities/community_members.js) + +@extends(templates/layout_normal) + +@section(main) +

getName() ?> - Edit members

+
+ + + + + + + + + + getUserId() !== Container::$request->user()->getUniqueId(); ?> + + + + + + + + + + + +
Owner
getUser()->getDisplayName() ?>getOwner() ? 'checked' : '' ?> />
+
+@endsection + +@section(pageScript) + +@endsection diff --git a/views/home.php b/views/home.php new file mode 100644 index 0000000..1a44cec --- /dev/null +++ b/views/home.php @@ -0,0 +1,28 @@ +@extends(templates/layout_normal) + +@section(main) +
+
+

Communities

+ 0): ?> + +

getName() ?>

+ + +

You have no community.

+ +
+

New community

+
+
+

Upcoming events

+ 0): ?> + + + + +

There is no upcoming event.

+ +
+
+@endsection diff --git a/views/index.php b/views/index.php deleted file mode 100644 index 557ec0f..0000000 --- a/views/index.php +++ /dev/null @@ -1,8 +0,0 @@ -@extends(templates/layout_normal) - -@section(main) -

-
-

This is the new .

-
-@endsection diff --git a/web.php b/web.php index aaa2601..ebe80da 100644 --- a/web.php +++ b/web.php @@ -12,7 +12,7 @@ if (!empty($_ENV['DEV'])) { Container::$routeCollection = new SokoWeb\Routing\RouteCollection(); -Container::$routeCollection->get('index', '', [RVR\Controller\HomeController::class, 'getIndex']); +Container::$routeCollection->get('home', '', [RVR\Controller\HomeController::class, 'getHome']); Container::$routeCollection->get('startSession', 'startSession.json', [RVR\Controller\HomeController::class, 'startSession']); Container::$routeCollection->group('login', function (SokoWeb\Routing\RouteCollection $routeCollection) { $routeCollection->get('login', '', [RVR\Controller\LoginController::class, 'getLoginForm']); @@ -41,6 +41,20 @@ Container::$routeCollection->group('account', function (SokoWeb\Routing\RouteCol $routeCollection->get('account.googleAuthenticate', 'googleAuthenticate', [RVR\Controller\UserController::class, 'getGoogleAuthenticateRedirect']); $routeCollection->get('account.googleAuthenticate-action', 'googleAuthenticate/code', [RVR\Controller\UserController::class, 'authenticateWithGoogle']); }); +Container::$routeCollection->get('searchUser', 'searchUser', [RVR\Controller\UserSearchController::class, 'searchUser']); +Container::$routeCollection->group('communities', function (SokoWeb\Routing\RouteCollection $routeCollection) { + $routeCollection->get('community-new', 'new', [RVR\Controller\CommunityController::class, 'getCommunityNew']); + $routeCollection->post('community-new-action', 'new', [RVR\Controller\CommunityController::class, 'saveCommunity']); + $routeCollection->group('{communityId}', function (SokoWeb\Routing\RouteCollection $routeCollection) { + $routeCollection->get('community', '', [RVR\Controller\CommunityController::class, 'getCommunityHome']); + $routeCollection->get('community-edit', 'edit', [RVR\Controller\CommunityController::class, 'getCommunityEdit']); + $routeCollection->post('community-edit-action', 'edit', [RVR\Controller\CommunityController::class, 'saveCommunity']); + $routeCollection->get('community-members', 'members', [RVR\Controller\CommunityController::class, 'getMembersEdit']); + $routeCollection->post('community-members-new', 'newMember', [RVR\Controller\CommunityController::class, 'newMember']); + $routeCollection->post('community-members-edit', 'editMember', [RVR\Controller\CommunityController::class, 'editMember']); + $routeCollection->post('community-members-delete', 'deleteMember', [RVR\Controller\CommunityController::class, 'deleteMember']); + }); +}); Container::$sessionHandler = new SokoWeb\Session\DatabaseSessionHandler();