Skip to content

Commit

Permalink
feature:
Browse files Browse the repository at this point in the history
- Docker bind mount for development
- Stimulus support
- Typescript support
- Add attendance mode where activity admins can take attendance of
  participants
  • Loading branch information
LuukBlankenstijn committed Jan 18, 2025
1 parent bfc2fd9 commit 3a32631
Show file tree
Hide file tree
Showing 25 changed files with 1,792 additions and 276 deletions.
1 change: 1 addition & 0 deletions .dockerignore
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@ public/data/meeting-documents/
public/data/meeting-notes/
public/data/photo/
public/styleguide/
public/js/dist
vendor/

# Language binaries are created during the docker build process or using 'make compilelang'
Expand Down
11 changes: 9 additions & 2 deletions Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,9 @@ rundev: builddev
@docker compose up -d --remove-orphans
@make replenish
@docker compose exec web rm -rf data/cache/module-config-cache.application.config.cache.php
@make translations-compile
@npm install
@npm run assets

migrate: replenish
@docker compose exec -it web ./orm migrations:migrate
Expand Down Expand Up @@ -84,9 +87,9 @@ getvendordir:

replenish:
@docker cp ./public "$(shell docker compose ps -q web)":/code
@docker compose exec web chown -R www-data:www-data /code/public
@docker compose exec web chown -R web-user:web-user /code/public
@docker cp ./data "$(shell docker compose ps -q web)":/code
@docker compose exec web chown -R www-data:www-data /code/data
@docker compose exec web chown -R web-user:web-user /code/data
@docker compose exec web rm -rf data/cache/module-config-cache.application.config.cache.php
@docker compose exec web composer dump-autoload --dev
@docker compose exec web ./orm orm:generate-proxies
Expand Down Expand Up @@ -134,6 +137,10 @@ translations:
msgattrib --no-obsolete -o $(TRANSLATIONS_DIR)/en.po $(TRANSLATIONS_DIR)/en.po && \
msgattrib --no-obsolete -o $(TRANSLATIONS_DIR)/nl.po $(TRANSLATIONS_DIR)/nl.po

translations-compile:
@msgfmt $(TRANSLATIONS_DIR)/en.po -o $(TRANSLATIONS_DIR)/en -c --strict -v
@msgfmt $(TRANSLATIONS_DIR)/nl.po -o $(TRANSLATIONS_DIR)/nl -c --strict -v

update: updatecomposer updatepackage updatecss updateglide updatedocker

loadenv:
Expand Down
10 changes: 10 additions & 0 deletions docker-compose.override.yml
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,9 @@ services:
restart: unless-stopped
nginx:
build: docker/nginx
volumes:
- ./public/js:/code/public/js:ro
- ./public/css:/code/public/css:ro
ports:
- "80:9200"
- "81:9201"
Expand All @@ -36,6 +39,10 @@ services:
- mysql
extra_hosts:
- "host.docker.internal:host-gateway"
volumes:
- ./public/js:/code/public/js:rw
- ./public/css:/code/public/css:rw
- ./module:/code/module
postfix:
image: mailhog/mailhog
env_file:
Expand All @@ -44,6 +51,9 @@ services:
- "8025:8025"
glide:
build: docker/glide
volumes:
- ./public/js:/code/public/js:rw
- ./public/css:/code/public/css:rw
matomo:
build: docker/matomo
depends_on:
Expand Down
61 changes: 19 additions & 42 deletions docker/web/development/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,15 +1,3 @@
# Compile the language files.
FROM alpine:latest AS gewisweb_translations
WORKDIR /code

RUN apk add --no-cache --virtual .runtime-deps \
gettext

COPY ./module/Application/language/*.po ./

RUN msgfmt en.po -o en -c --strict -v \
&& msgfmt nl.po -o nl -c --strict -v

# Install dependencies and create final image.
FROM php:8.3-fpm-alpine AS gewisweb_web_development_base
WORKDIR /code
Expand Down Expand Up @@ -86,6 +74,10 @@ RUN apk add --no-cache --virtual .build-deps \

RUN sed -i 's/<policy domain="coder" rights="none" pattern="PDF" \/>/<policy domain="coder" rights="read|write" pattern="PDF" \/>/g' /etc/ImageMagick-7/policy.xml

RUN addgroup -g 1000 web-user && adduser -u 1000 -G web-user -D web-user
RUN chown -R web-user:web-user /code
USER web-user

# Install composer and dependencies.
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
COPY ./composer.json ./composer.lock ./
Expand All @@ -97,52 +89,37 @@ ENV COMPOSER_ALLOW_SUPERUSER=1

RUN composer install

# Compile the SCSS files.
FROM node:lts-alpine AS gewisweb_web_styles
WORKDIR /code

COPY ./package.json ./package-lock.json ./
RUN npm install --omit=dev

RUN mkdir public && mkdir public/scss && mkdir public/css

COPY --from=gewisweb_web_development_base /code/vendor ./vendor
COPY ./resources/scss ./resources/scss/

RUN npm run scss

# Create the final image.
FROM gewisweb_web_development_base AS gewisweb_web_development

# Copy patches for dependencies that cannot be patched through composer. If you are not a member of the
# ApplicatieBeheerCommissie comment the line below.
COPY --from=abc.docker-registry.gewis.nl/web/gewisweb/patches:latest . /code

COPY --chown=www-data:www-data ./docker/web/development/php.ini /usr/local/etc/php/conf.d/default.ini
COPY --chown=www-data:www-data ./docker/web/development/php-fpm.conf /usr/local/etc/php-fpm.d/zz-gewisweb.conf
COPY --chown=www-data:www-data ./config/autoload/local.development.php.dist ./config/autoload/local.php
COPY --chown=www-data:www-data ./config/autoload/doctrine.local.development.php.dist ./config/autoload/doctrine.local.php
COPY --chown=www-data:www-data ./config/autoload/gewisdb.local.php.dist ./config/autoload/gewisdb.local.php
COPY --chown=www-data:www-data ./config/autoload/laminas-developer-tools.local.php.dist ./config/autoload/laminas-developer-tools.local.php
COPY --chown=web-user:web-user ./docker/web/development/php.ini /usr/local/etc/php/conf.d/default.ini
COPY --chown=web-user:web-user ./docker/web/development/php-fpm.conf /usr/local/etc/php-fpm.d/zz-gewisweb.conf
COPY --chown=web-user:web-user ./config/autoload/local.development.php.dist ./config/autoload/local.php
COPY --chown=web-user:web-user ./config/autoload/doctrine.local.development.php.dist ./config/autoload/doctrine.local.php
COPY --chown=web-user:web-user ./config/autoload/gewisdb.local.php.dist ./config/autoload/gewisdb.local.php
COPY --chown=web-user:web-user ./config/autoload/laminas-developer-tools.local.php.dist ./config/autoload/laminas-developer-tools.local.php

COPY --chown=www-data:www-data ./docker/web/development/crontab /etc/cron.d/crontab
USER root
COPY --chown=web-user:web-user ./docker/web/development/crontab /etc/cron.d/crontab
RUN chmod 0644 /etc/cron.d/crontab && crontab /etc/cron.d/crontab

COPY --chown=www-data:www-data ./docker/web/development/docker-entrypoint.sh ./docker-entrypoint.sh
user web-user

COPY --chown=web-user:web-user ./docker/web/development/docker-entrypoint.sh ./docker-entrypoint.sh
RUN chmod 0775 ./docker-entrypoint.sh

COPY --chown=www-data:www-data . /code
COPY --chown=www-data:www-data --from=gewisweb_translations /code/*.mo /code/module/Application/language/
COPY --chown=www-data:www-data --from=gewisweb_web_styles /code/public/css/gewis-theme.css /code/public/css/gewis-theme.css
COPY --chown=web-user:web-user . /code

USER web-user
RUN cp -R ./vendor/fortawesome/font-awesome/sprites/. ./public/sprites/fontawesome
RUN cp -R ./vendor/fortawesome/font-awesome/webfonts/. ./public/fonts/fontawesome

ENV PHP_IDE_CONFIG="serverName=gewis.nl"

RUN composer dump-autoload

ARG GIT_COMMIT
ENV GIT_COMMIT=${GIT_COMMIT}

VOLUME ["/code/data", "/code/public"]

ENTRYPOINT ["/bin/sh", "/code/docker-entrypoint.sh"]
8 changes: 5 additions & 3 deletions docker/web/production/Dockerfile
Original file line number Diff line number Diff line change
Expand Up @@ -87,7 +87,7 @@ ENV COMPOSER_ALLOW_SUPERUSER=1
RUN composer install -o --no-dev

# Compile the SCSS files.
FROM node:lts-alpine AS gewisweb_web_styles
FROM node:lts-alpine AS gewisweb_web_assets
WORKDIR /code

COPY ./package.json ./package-lock.json ./
Expand All @@ -97,8 +97,9 @@ RUN mkdir public && mkdir public/scss && mkdir public/css

COPY --from=gewisweb_web_production_base /code/vendor ./vendor
COPY ./resources/scss ./resources/scss/
COPY ./public/js/controllers ./public/js/controllers

RUN npm run scss
RUN npm run assets

# Create the final image.
FROM gewisweb_web_production_base AS gewisweb_web_production
Expand All @@ -120,7 +121,8 @@ RUN chmod 0775 ./docker-entrypoint.sh

COPY --chown=www-data:www-data . /code
COPY --chown=www-data:www-data --from=gewisweb_translations /code/*.mo /code/module/Application/language/
COPY --chown=www-data:www-data --from=gewisweb_web_styles /code/public/css/gewis-theme.css /code/public/css/gewis-theme.css
COPY --chown=www-data:www-data --from=gewisweb_web_assets /code/public/css/gewis-theme.css /code/public/css/gewis-theme.css
COPY --chown=www-data:www-data --from=gewisweb_web_assets /code/public/js/dist /code/public/js/dist
RUN cp -R ./vendor/fortawesome/font-awesome/sprites/. ./public/sprites/fontawesome
RUN cp -R ./vendor/fortawesome/font-awesome/webfonts/. ./public/fonts/fontawesome

Expand Down
12 changes: 12 additions & 0 deletions module/Activity/config/module.config.php
Original file line number Diff line number Diff line change
Expand Up @@ -232,6 +232,18 @@
],
],
],
'markPresent' => [
'type' => Segment::class,
'options' => [
'route' => '/markPresent/:id',
'constraints' => [
'id' => '\d+',
],
'defaults' => [
'action' => 'markPresent',
],
],
],
],
],
'activity_calendar' => [
Expand Down
75 changes: 75 additions & 0 deletions module/Activity/src/Controller/AdminController.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@

namespace Activity\Controller;

use Activity\Mapper\Signup;
use Activity\Mapper\Signup as SignupMapper;
use Activity\Model\Activity as ActivityModel;
use Activity\Model\Signup as SignupModel;
use Activity\Service\AclService;
use Activity\Service\Activity as ActivityService;
use Activity\Service\ActivityQuery as ActivityQueryService;
Expand All @@ -25,6 +27,7 @@
use Laminas\Session\Container as SessionContainer;
use Laminas\Stdlib\Parameters;
use Laminas\Stdlib\ParametersInterface;
use Laminas\View\Model\JsonModel;
use Laminas\View\Model\ViewModel;
use User\Permissions\NotAllowedException;

Expand Down Expand Up @@ -509,4 +512,76 @@ public function viewAction(): ViewModel

return new ViewModel($result);
}

public function markPresentAction(): JsonModel
{
if (!$this->getRequest()->isPost()) {
$this->getResponse()->setStatusCode(405);

return new JsonModel([
'Error' => $this->translator->translate('You can only make POST requests to this endpoint'),
]);
}

$signupId = (int) $this->params()->fromRoute('id');
/** @var SignupModel $signup */
$signup = $this->signupMapper->getSignupById($signupId);
if (null === $signup) {

Check failure on line 529 in module/Activity/src/Controller/AdminController.php

View workflow job for this annotation

GitHub Actions / PHPStan

Strict comparison using === between null and Activity\Model\Signup will always evaluate to false.
$this->getResponse()->setStatusCode(400);

return new JsonModel(['Error' => $this->translator->translate('Signup not found')]);
}

$signupList = $signup->getSignupList();
$activity = $signupList->getActivity();

if (!$this->aclService->isAllowed('viewParticipants', $signupList)) {
$this->getResponse()->setStatusCode(401);

return new JsonModel([
'Error' => $this->translator->translate(
'You are not allowed to view the participants of this activity',
),
]);
}

if (
new DateTime() < $activity->getBeginTime()->modify('-30 min') ||
new DateTime() > $activity->getEndTime()->modify('+30 min')
) {
$this->getResponse()->setStatusCode(400);

return new JsonModel([
'Error' => $this->translator->translate(
'Presence mode is not open right now',
),
]);
}

$entityManager = $this->signupMapper->getEntityManager();

$signup->setPresent(true);
$entityManager->persist($signup);

$signupList->setPresenceTaken(true);
$entityManager->persist($signupList);

$entityManager->flush();

/** @var Signup[] $signups */
$signups = $entityManager
->getRepository(SignupModel::class)
->findBy(['signupList' => $signup->getSignupList()->getActivity()->getId()]);

$response = [];
foreach ($signups as $signup) {
if (!$signup->getPresent()) {

Check failure on line 578 in module/Activity/src/Controller/AdminController.php

View workflow job for this annotation

GitHub Actions / PHPStan

Call to an undefined method Activity\Mapper\Signup::getPresent().

Check failure on line 578 in module/Activity/src/Controller/AdminController.php

View workflow job for this annotation

GitHub Actions / Psalm

UndefinedMethod

module/Activity/src/Controller/AdminController.php:578:27: UndefinedMethod: Method Activity\Mapper\Signup::getPresent does not exist (see https://psalm.dev/022)
continue;
}

$response[] = $signup->getId();

Check failure on line 582 in module/Activity/src/Controller/AdminController.php

View workflow job for this annotation

GitHub Actions / PHPStan

Call to an undefined method Activity\Mapper\Signup::getId().

Check failure on line 582 in module/Activity/src/Controller/AdminController.php

View workflow job for this annotation

GitHub Actions / Psalm

UndefinedMethod

module/Activity/src/Controller/AdminController.php:582:36: UndefinedMethod: Method Activity\Mapper\Signup::getId does not exist (see https://psalm.dev/022)
}

return new JsonModel($response);

Check failure on line 585 in module/Activity/src/Controller/AdminController.php

View workflow job for this annotation

GitHub Actions / PHPStan

Parameter #1 $variables of class Laminas\View\Model\JsonModel constructor expects array<string, mixed>|ArrayAccess<string, mixed>|Traversable<string, mixed>|null, array<int<0, max>, mixed> given.

Check failure on line 585 in module/Activity/src/Controller/AdminController.php

View workflow job for this annotation

GitHub Actions / Psalm

InvalidArgument

module/Activity/src/Controller/AdminController.php:585:30: InvalidArgument: Argument 1 of Laminas\View\Model\JsonModel::__construct expects ArrayAccess<string, mixed>|iterable<string, mixed>|null, but list<mixed> provided (see https://psalm.dev/004)
}
}
8 changes: 8 additions & 0 deletions module/Activity/src/Mapper/Signup.php
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,14 @@ public function getSignupsOlderThan5Years(): array
return $qb->getQuery()->getResult();
}

/**
* Get Signup by id
*/
public function getSignupById(int $id): ?SignupModel
{
return $this->getEntityManager()->getRepository(SignupModel::class)->find($id);
}

protected function getRepositoryName(): string
{
return UserSignupModel::class;
Expand Down
24 changes: 24 additions & 0 deletions module/Activity/src/Model/Signup.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
use DateTimeInterface;
use Doctrine\Common\Collections\ArrayCollection;
use Doctrine\Common\Collections\Collection;
use Doctrine\ORM\Mapping\Column;
use Doctrine\ORM\Mapping\DiscriminatorColumn;
use Doctrine\ORM\Mapping\DiscriminatorMap;
use Doctrine\ORM\Mapping\Entity;
Expand All @@ -29,6 +30,7 @@
* activity_id: int,
* signupList_id: int,
* fieldValues: ImportedSignupFieldValueGdprArrayType[],
* present: bool,
* }
*/
#[Entity]
Expand Down Expand Up @@ -75,6 +77,12 @@ abstract class Signup
)]
protected Collection $fieldValues;

/**
* Determines if the user was present or not
*/
#[Column(type: 'boolean')]
protected bool $present = false;

public function __construct()
{
$this->fieldValues = new ArrayCollection();
Expand Down Expand Up @@ -106,6 +114,22 @@ public function getFieldValues(): Collection
return $this->fieldValues;
}

/**
* Get presence of the user
*/
public function getPresent(): bool
{
return $this->present;
}

/**
* Set presence of the user
*/
public function setPresent(bool $present): void
{
$this->present = $present;
}

/**
* Get the full name of the user whom signed up for the SignupList.
*/
Expand Down
Loading

0 comments on commit 3a32631

Please sign in to comment.