diff --git a/assets/less/components/alert.less b/assets/less/components/alert.less index 66a3b3d..d49857d 100644 --- a/assets/less/components/alert.less +++ b/assets/less/components/alert.less @@ -43,4 +43,10 @@ border: 1px solid @alert-success-border-color; background: @alert-success-color; } + + &--error { + color: @alert-error-text-color; + border: 1px solid @alert-error-border-color; + background: @alert-error-color; + } } diff --git a/assets/less/settings.less b/assets/less/settings.less index 97cacd7..54d2e83 100644 --- a/assets/less/settings.less +++ b/assets/less/settings.less @@ -59,6 +59,10 @@ @alert-primary-border-color: #b5cce3; @alert-primary-text-color: #172a3e; +@alert-error-color: #f6d0d0; +@alert-error-border-color: #d99797; +@alert-error-text-color: #3a1d1d; + // Forms @form-error-color: red; @form-text-input-background-color: #fff; diff --git a/config/app_routes/frontpageconfig.yaml b/config/app_routes/frontpageconfig.yaml index 31a4cde..bdca53e 100644 --- a/config/app_routes/frontpageconfig.yaml +++ b/config/app_routes/frontpageconfig.yaml @@ -2,3 +2,8 @@ frontpageconfig: controller: App\Controller\FrontPageConfigurationController::frontPageConfig path: /frontpageconfig methods: [GET, POST] + +frontpageconfig_removeannouncement: + controller: App\Controller\FrontPageConfigurationController::removeAnnouncement + path: /frontpageconfig/remove_announcement + methods: [POST] diff --git a/src/Controller/FrontController.php b/src/Controller/FrontController.php index 1e1f47e..22addc4 100644 --- a/src/Controller/FrontController.php +++ b/src/Controller/FrontController.php @@ -4,11 +4,13 @@ use App\Entity\User; use App\Entity\ForumConfiguration; +use App\Entity\Submission; use App\Repository\ForumRepository; use App\Repository\ForumConfigurationRepository; use App\Repository\SubmissionRepository; use App\Utils\PermissionsChecker; use Symfony\Component\HttpFoundation\Response; +use Doctrine\ORM\EntityManager; /** * Actions that list submissions across many forums. @@ -28,10 +30,14 @@ * instead. */ final class FrontController extends AbstractController { - public function front(ForumRepository $fr, SubmissionRepository $sr, ForumConfigurationRepository $fcr, string $sortBy, int $page) { + public function front(ForumRepository $fr, SubmissionRepository $sr, ForumConfigurationRepository $fcr, string $sortBy, int $page, EntityManager $em) { $user = $this->getUser(); $siteConfig = $fcr->findSitewide(); + $announcementSubmission = null; + if($siteConfig->getAnnouncementSubmissionId() != null) { + $announcementSubmission = $em->find("App\\Entity\\Submission", $siteConfig->getAnnouncementSubmissionId()); + } if (!$user instanceof User) { //$listing = User::FRONT_FEATURED; @@ -45,20 +51,20 @@ public function front(ForumRepository $fr, SubmissionRepository $sr, ForumConfig switch ($listing) { case User::FRONT_SUBSCRIBED: - return $this->subscribed($fr, $sr, $sortBy, $page, $siteConfig); + return $this->subscribed($fr, $sr, $sortBy, $page, $siteConfig, $announcementSubmission); case User::FRONT_FEATURED: - return $this->featured($fr, $sr, $sortBy, $page, $siteConfig); + return $this->featured($fr, $sr, $sortBy, $page, $siteConfig, $announcementSubmission); case User::FRONT_ALL: //return $this->all($sr, $sortBy, $page, $siteConfig); - return $this->all($fr, $sr, $sortBy, $page, $siteConfig); + return $this->all($fr, $sr, $sortBy, $page, $siteConfig, $announcementSubmission); case User::FRONT_MODERATED: - return $this->moderated($fr, $sr, $sortBy, $page, $siteConfig); + return $this->moderated($fr, $sr, $sortBy, $page, $siteConfig, $announcementSubmission); default: throw new \InvalidArgumentException('bad front page selection'); } } - public function featured(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig) { + public function featured(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig, Submission $announcementSubmission) { $forums = $fr->findFeaturedForumNames(); $submissions = $sr->findFrontPageSubmissions($forums, $sortBy, $page); @@ -68,10 +74,11 @@ public function featured(ForumRepository $fr, SubmissionRepository $sr, string $ 'submissions' => $submissions, 'sort_by' => $sortBy, 'announcement' => $siteConfig->getAnnouncement(), + 'announcementSubmission' => $announcementSubmission, ]); } - public function subscribed(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig) { + public function subscribed(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig, Submission $announcementSubmission) { $this->denyAccessUnlessGranted('ROLE_USER'); $forums = $fr->findSubscribedForumNames($this->getUser()); @@ -90,6 +97,7 @@ public function subscribed(ForumRepository $fr, SubmissionRepository $sr, string 'sort_by' => $sortBy, 'submissions' => $submissions, 'announcement' => $siteConfig->getAnnouncement(), + 'announcementSubmission' => $announcementSubmission, ]); } @@ -100,7 +108,7 @@ public function subscribed(ForumRepository $fr, SubmissionRepository $sr, string * * @return Response */ - public function all(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig) { + public function all(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig, Submission $announcementSubmission) { # Added for v1. $admin = PermissionsChecker::isAdmin($this->getUser()); $forums = $fr->findAllForumNames(); @@ -112,10 +120,11 @@ public function all(ForumRepository $fr, SubmissionRepository $sr, string $sortB 'sort_by' => $sortBy, 'submissions' => $submissions, 'announcement' => $siteConfig->getAnnouncement(), + 'announcementSubmission' => $announcementSubmission, ]); } - public function moderated(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig) { + public function moderated(ForumRepository $fr, SubmissionRepository $sr, string $sortBy, int $page, ForumConfiguration $siteConfig, Submission $announcementSubmission) { $this->denyAccessUnlessGranted('ROLE_USER'); $forums = $fr->findModeratedForumNames($this->getUser()); @@ -127,6 +136,7 @@ public function moderated(ForumRepository $fr, SubmissionRepository $sr, string 'sort_by' => $sortBy, 'submissions' => $submissions, 'announcement' => $siteConfig->getAnnouncement(), + 'announcementSubmission' => $announcementSubmission, ]); } diff --git a/src/Controller/FrontPageConfigurationController.php b/src/Controller/FrontPageConfigurationController.php index 0da63cc..ce612a4 100644 --- a/src/Controller/FrontPageConfigurationController.php +++ b/src/Controller/FrontPageConfigurationController.php @@ -4,14 +4,16 @@ use App\Entity\User; use App\Entity\ForumConfiguration; +use App\Entity\Submission; use App\Repository\ForumRepository; use App\Repository\ForumConfigurationRepository; use App\Repository\SubmissionRepository; +use App\Repository\UserRepository; use Symfony\Component\HttpFoundation\Response; use Sensio\Bundle\FrameworkExtraBundle\Configuration\Entity; use Sensio\Bundle\FrameworkExtraBundle\Configuration\IsGranted; -use App\Form\ForumConfigurationType; -use App\Form\Model\ForumConfigurationData; +use App\Form\NewForumAnnouncementType; +use App\Form\Model\NewForumAnnouncementData; use Doctrine\ORM\EntityManager; use Symfony\Component\HttpFoundation\Request; @@ -20,37 +22,87 @@ * @IsGranted("ROLE_ADMIN") */ final class FrontPageConfigurationController extends AbstractController { - public function frontPageConfig(ForumRepository $fr, SubmissionRepository $sr, ForumConfigurationRepository $fcr, EntityManager $em, Request $request) { - $data = new ForumConfigurationData($fcr->findSitewide()); - $form = $this->createForm(ForumConfigurationType::class, $data); + public function frontPageConfig( + ForumRepository $fr, + SubmissionRepository $sr, + ForumConfigurationRepository $fcr, + UserRepository $ur, + EntityManager $em, + Request $request + ) { + $announcementForumName = "announcements"; + $data = new NewForumAnnouncementData(); + + $form = $this->createForm(NewForumAnnouncementType::class, $data); $form->handleRequest($request); $message = ""; + $messageClass = ""; if ($form->isSubmitted() && $form->isValid()) { - $fc = $data->toForumConfiguration(); + // Find the user and forum for submission. + $user = $ur->loadUserByUsername($this->getUser()->getUsername()); + $forum = $fr->findOneByCaseInsensitiveName($announcementForumName); + + if($forum != null) { + // Create the submission. + $submission = new Submission( + $data->threadTitle, + null, + $data->threadContent, + $forum, + $user, + null + ); + $em->persist($submission); + $em->flush(); - // For sitewide settings, we need to force this to null. - $fc->setForumId(null); + // Load the current announcement's row id. Sitewide announcemnts have null forum id. + $fc = $fcr->findSitewide(); + $fc->setAnnouncementSubmissionId($submission->getId()); + $fc->setAnnouncement($data->announcement); + $fc->setForumId(null); - if($fc->getId() == null || trim($fc->getId()) == "") $em->persist($fc); - else - $em->merge($fc); + $em->flush(); - $em->flush(); + // After saving, pull the data back down again. + $data = new NewForumAnnouncementData(); + $form = $this->createForm(NewForumAnnouncementType::class, $data); - // After saving, pull the data back down again. - $data = new ForumConfigurationData($fcr->findSitewide()); - $form = $this->createForm(ForumConfigurationType::class, $data); + $message = "front_page_configuration_form.announcement_saved"; + $messageClass = "success"; + } else { + $message = "front_page_configuration_form.announcement_forum_error"; + $messageClass = "error"; + } + } - $message = "front_page_configuration_form.message_saved"; + // Load the current sitewide so we can show the announcement. + $frontpageconfig = $fcr->findSitewide(); + $announcementSubmission = null; + if($frontpageconfig->getAnnouncementSubmissionId() != null) { + $announcementSubmission = $em->find("App\\Entity\\Submission", $frontpageconfig->getAnnouncementSubmissionId()); } return $this->render('frontpageconfig/frontpageconfig.html.twig', [ 'form' => $form->createView(), 'message' => $message, + 'messageClass' => $messageClass, + 'current_announcement' => $frontpageconfig->getAnnouncement(), + 'announcementSubmission' => $announcementSubmission, ]); } + + public function removeAnnouncement(ForumRepository $fr, SubmissionRepository $sr, ForumConfigurationRepository $fcr, EntityManager $em, Request $request) { + $fc = $fcr->findSitewide(); + + $fc->setAnnouncement(null); + $fc->setAnnouncementSubmissionId(null); + $em->merge($fc); + $em->flush(); + + return $this->redirectToRoute('frontpageconfig'); + } } diff --git a/src/Entity/ForumConfiguration.php b/src/Entity/ForumConfiguration.php index 4a2309b..46d9a91 100644 --- a/src/Entity/ForumConfiguration.php +++ b/src/Entity/ForumConfiguration.php @@ -39,6 +39,13 @@ class ForumConfiguration { */ private $announcement; + /** + * @ORM\Column(type="bigint", nullable=true) + * + * @var int|null + */ + private $announcementSubmissionId; + public function __construct($forumId) { $this->forumId = $forumId; } @@ -66,4 +73,12 @@ public function getAnnouncement() { public function setAnnouncement($announcement) { $this->announcement = $announcement; } + + public function getAnnouncementSubmissionId() { + return $this->announcementSubmissionId; + } + + public function setAnnouncementSubmissionId($id) { + $this->announcementSubmissionId = $id; + } } diff --git a/src/Form/Model/ForumConfigurationData.php b/src/Form/Model/NewForumAnnouncementData.php similarity index 57% rename from src/Form/Model/ForumConfigurationData.php rename to src/Form/Model/NewForumAnnouncementData.php index 32f3dee..c1b3926 100644 --- a/src/Form/Model/ForumConfigurationData.php +++ b/src/Form/Model/NewForumAnnouncementData.php @@ -5,7 +5,7 @@ use App\Entity\ForumConfiguration; use Symfony\Component\Validator\Constraints as Assert; -class ForumConfigurationData { +class NewForumAnnouncementData { /** * @var int */ @@ -21,10 +21,22 @@ class ForumConfigurationData { */ public $announcement; - public function __construct(ForumConfiguration $fc) { - $this->id = $fc->getId(); - $this->forumId = $fc->getForumId(); - $this->announcement = $fc->getAnnouncement(); + /** + * @var string + */ + public $threadTitle; + + /** + * @var string + */ + public $threadContent; + + public function __construct(ForumConfiguration $fc = null) { + if($fc != null) { + $this->id = $fc->getId(); + $this->forumId = $fc->getForumId(); + $this->announcement = $fc->getAnnouncement(); + } } public function toForumConfiguration(): ForumConfiguration { diff --git a/src/Form/ForumConfigurationType.php b/src/Form/NewForumAnnouncementType.php similarity index 61% rename from src/Form/ForumConfigurationType.php rename to src/Form/NewForumAnnouncementType.php index e9c8b4e..6a4c71a 100644 --- a/src/Form/ForumConfigurationType.php +++ b/src/Form/NewForumAnnouncementType.php @@ -2,7 +2,7 @@ namespace App\Form; -use App\Form\Model\ForumConfigurationData; +use App\Form\Model\NewForumAnnouncementData; use Symfony\Component\Form\AbstractType; use App\Form\Type\MarkdownType; use Symfony\Component\Form\Extension\Core\Type\TextType; @@ -12,12 +12,20 @@ use Symfony\Component\Form\FormBuilderInterface; use Symfony\Component\OptionsResolver\OptionsResolver; -class ForumConfigurationType extends AbstractType { +class NewForumAnnouncementType extends AbstractType { public function buildForm(FormBuilderInterface $builder, array $options) { $builder - ->add('announcement', MarkdownType::class, [ + ->add('announcement', TextType::class, [ 'label' => 'front_page_configuration_form.announcement', - 'required' => false + 'required' => true + ]) + ->add('threadTitle', TextType::class, [ + 'label' => 'front_page_configuration_form.thread_title', + 'required' => true + ]) + ->add('threadContent', MarkdownType::class, [ + 'label' => 'front_page_configuration_form.thread_content', + 'required' => true ]) ->add('id', HiddenType::class, []) ->add('forumId', HiddenType::class, []) @@ -28,7 +36,7 @@ public function buildForm(FormBuilderInterface $builder, array $options) { public function configureOptions(OptionsResolver $resolver) { $resolver->setDefaults([ - 'data_class' => ForumConfigurationData::class, + 'data_class' => NewForumAnnouncementData::class, ]); } } diff --git a/src/Migrations/Version20180401054730.php b/src/Migrations/Version20180401054730.php new file mode 100644 index 0000000..593b924 --- /dev/null +++ b/src/Migrations/Version20180401054730.php @@ -0,0 +1,41 @@ +abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('ALTER TABLE forum_configuration ADD announcement_submission_id BIGINT DEFAULT NULL'); + $this->addSql('ALTER TABLE moderators ALTER id TYPE UUID'); + $this->addSql('ALTER TABLE moderators ALTER id DROP DEFAULT'); + $this->addSql('ALTER TABLE wiki_revisions ALTER id TYPE UUID'); + $this->addSql('ALTER TABLE wiki_revisions ALTER id DROP DEFAULT'); + $this->addSql('ALTER TABLE forum_subscriptions ALTER id TYPE UUID'); + $this->addSql('ALTER TABLE forum_subscriptions ALTER id DROP DEFAULT'); + } + + public function down(Schema $schema) + { + // this down() migration is auto-generated, please modify it to your needs + $this->abortIf($this->connection->getDatabasePlatform()->getName() !== 'postgresql', 'Migration can only be executed safely on \'postgresql\'.'); + + $this->addSql('CREATE SCHEMA public'); + $this->addSql('ALTER TABLE forum_configuration DROP announcement_submission_id'); + $this->addSql('ALTER TABLE moderators ALTER id TYPE UUID'); + $this->addSql('ALTER TABLE moderators ALTER id DROP DEFAULT'); + $this->addSql('ALTER TABLE forum_subscriptions ALTER id TYPE UUID'); + $this->addSql('ALTER TABLE forum_subscriptions ALTER id DROP DEFAULT'); + $this->addSql('ALTER TABLE wiki_revisions ALTER id TYPE UUID'); + $this->addSql('ALTER TABLE wiki_revisions ALTER id DROP DEFAULT'); + } +} diff --git a/templates/front/base.html.twig b/templates/front/base.html.twig index 2de01b3..93a0da4 100644 --- a/templates/front/base.html.twig +++ b/templates/front/base.html.twig @@ -18,7 +18,11 @@ {% endblock %} {% block body %} - {% if announcement != null %}
{% endif %} + {% if announcement != null %} + + {% endif %}