Skip to content

Commit da0d008

Browse files
Update preferences page. (#394)
1 parent e11d8cf commit da0d008

File tree

11 files changed

+212
-78
lines changed

11 files changed

+212
-78
lines changed

assets/js/profile/preference.js

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
const member = document.getElementById('member').value
2+
const preferences = document.querySelectorAll( '.preference')
3+
4+
preferences.forEach(
5+
async preference => {
6+
preference.addEventListener('change', async (event) => {
7+
let value = null
8+
if (event.target.type === 'checkbox') {
9+
value = event.target.checked
10+
} else {
11+
value = event.target.value
12+
}
13+
14+
const form = new FormData();
15+
form.append('member', member);
16+
form.append('preference', preference.id.replace('preferences_', ''));
17+
form.append('value', value);
18+
19+
await fetch("/members/update/preference", { method: 'POST', body: form })
20+
.then(() => { /* Nothing to do here */ })
21+
22+
console.log(form)
23+
})
24+
}
25+
)

assets/tailwindcss/tailwind.css

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,6 +38,7 @@
3838

3939
--radius-4: 4px;
4040
--radius-5: 5px;
41+
--radius-6: 6px;
4142
--radius-8: 8px;
4243
--radius-full: 100%;
4344

src/Command/MigrateDatabaseCommand.php

Lines changed: 20 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
use Doctrine\ORM\EntityManagerInterface;
1515
use Doctrine\ORM\EntityRepository;
1616
use Exception;
17+
use Symfony\Component\Console\Attribute\Argument;
1718
use Symfony\Component\Console\Attribute\AsCommand;
1819
use Symfony\Component\Console\Command\Command;
1920
use Symfony\Component\Console\Helper\ProgressBar;
@@ -164,13 +165,15 @@ public function __construct(
164165
$this->connection = $this->entityManager->getConnection();
165166
}
166167

167-
public function __invoke(InputInterface $input, OutputInterface $output): int
168+
public function __invoke(InputInterface $input, OutputInterface $output, #[Argument] int $offset): int
168169
{
169170
$this->io = new SymfonyStyle($input, $output);
170171
$this->io->success('Migrating old profiles.');
171172

172-
$this->connection->executeStatement('SET FOREIGN_KEY_CHECKS=0;');
173-
$this->connection->executeStatement('TRUNCATE `address`; TRUNCATE `member_translations`; TRUNCATE `member_language_level`; TRUNCATE `friend`; TRUNCATE `member`;');
173+
if (0 === $offset) {
174+
$this->connection->executeStatement('SET FOREIGN_KEY_CHECKS=0;');
175+
$this->connection->executeStatement('TRUNCATE `address`; TRUNCATE `member_translations`; TRUNCATE `member_language_level`; TRUNCATE `friend`; TRUNCATE `member`;');
176+
}
174177

175178
$sql = "SELECT COUNT(m.id) FROM members m WHERE m.status IN ('" . implode("', '", self::MIGRATED_STATUSES) . "')";
176179

@@ -190,24 +193,24 @@ public function __invoke(InputInterface $input, OutputInterface $output): int
190193
}
191194

192195
$this->errorMembers = [];
193-
$batchSize = 2000;
196+
$batchSize = 20000;
194197

195-
$this->progressBar = new ProgressBar($output, $countOfMembers);
198+
$this->progressBar = new ProgressBar($output, $batchSize);
196199
$this->progressBar->setFormat(
197-
"<fg=white;bg=green>\n %info:-60s% \n</>\n%current%/%max% [%bar%] %percent:3s%%\n%elapsed:-10% %%estimated:-10s% %memory:20s%\nLast error: %error%"
200+
"<fg=white;bg=green>\n %info:-60s% \n</>\n%current%/%max% [%bar%] %percent:3s%%\n%elapsed:-10s% %estimated:-10s% %memory:20s%\nLast error: %error%"
198201
);
199-
$this->progressBar->setMessage("Migrating {$countOfMembers} members to new member table including translations.", 'info');
202+
$this->progressBar->setMessage("Migrating {$countOfMembers} members starting at {$offset} to new member table including translations.", 'info');
200203
$this->progressBar->setMessage('none', 'error');
201204
$this->progressBar->minSecondsBetweenRedraws(10.0);
202205
$this->progressBar->start();
203206

204207
// Make sure the tables member and member_translations are empty
205208

206209
try {
207-
for ($current = 0; $current < $countOfMembers; $current += $batchSize) {
208-
$this->migrateMembersData($current, $batchSize);
209-
}
210-
$this->reportErrors();
210+
// for ($current = 0; $current < $countOfMembers; $current += $batchSize) {
211+
$this->migrateMembersData($offset, $batchSize);
212+
// }
213+
$this->reportErrors($offset);
211214
} finally {
212215
$this->connection->executeStatement('SET FOREIGN_KEY_CHECKS=1;');
213216
}
@@ -243,6 +246,7 @@ private function migrateMembersData(int $current, int $batchSize): void
243246
$this->progressBar->advance();
244247
unset($member);
245248
}
249+
unset($members);
246250
}
247251

248252
private function migrateMemberData(array $member): void
@@ -345,6 +349,8 @@ private function migrateMemberAddress(mixed $member): void
345349
} catch (Exception $e) {
346350
$this->progressBar->setMessage($member['Username'], 'error');
347351
$this->addErrorAddress($member, $e->getMessage());
352+
} finally {
353+
$this->entityManager->detach($city);
348354
}
349355
}
350356

@@ -402,6 +408,7 @@ private function migrateMemberTranslations(array $member): void
402408
}
403409
}
404410
}
411+
unset($processedTranslations, $memberTranslations);
405412

406413
$values = substr($queryString, 2);
407414

@@ -669,10 +676,10 @@ private function migrateLanguageLevel(string $level): string
669676
}
670677
}
671678

672-
private function reportErrors(): void
679+
private function reportErrors(int $offset): void
673680
{
674681
if (!empty($this->errorMembers)) {
675-
$file = fopen('migrateMembers.errors.txt', 'w');
682+
$file = fopen("migrateMembers.errors-{$offset}.txt", 'w');
676683
$countOfErrorMembers = 0;
677684
foreach ($this->errorMembers as $errors) {
678685
$countOfErrorMembers += \count($errors);

src/Controller/PreferenceController.php

Lines changed: 51 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,27 @@
33
namespace App\Controller;
44

55
use App\Entity\Member;
6+
use App\Entity\Preference;
67
use App\Form\PreferencesType;
78
use App\Model\PreferenceModel;
89
use App\Utilities\ChangeProfilePictureGlobals;
910
use App\Utilities\ProfileSubmenu;
1011
use Doctrine\ORM\EntityManagerInterface;
1112
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
13+
use Symfony\Component\Form\Extension\Core\Type\TextType;
1214
use Symfony\Component\HttpFoundation\RedirectResponse;
1315
use Symfony\Component\HttpFoundation\Request;
1416
use Symfony\Component\HttpFoundation\Response;
1517
use Symfony\Component\Routing\Attribute\Route;
1618

1719
class PreferenceController extends AbstractController
1820
{
21+
public function __construct(
22+
private readonly PreferenceModel $preferenceModel,
23+
private readonly EntityManagerInterface $entityManager,
24+
) {
25+
}
26+
1927
#[Route(path: '/mypreferences', name: 'mypreferences_redirect')]
2028
public function redirectMyPreferences(): RedirectResponse
2129
{
@@ -27,9 +35,7 @@ public function preferences(
2735
Request $request,
2836
Member $member,
2937
ProfileSubmenu $profileSubmenu,
30-
PreferenceModel $preferenceModel,
3138
ChangeProfilePictureGlobals $globals,
32-
EntityManagerInterface $entityManager,
3339
): Response {
3440
/** Member must be the logged in member to be able to access this page.
3541
* @var Member $loggedInMember
@@ -39,8 +45,8 @@ public function preferences(
3945
return $this->redirectToRoute('preferences', ['username' => $loggedInMember->getUsername()]);
4046
}
4147

42-
$preferences = $preferenceModel->getPreferences();
43-
$memberPreferences = $preferenceModel->getMemberPreferences($loggedInMember, $preferences);
48+
$preferences = $this->preferenceModel->getPreferences();
49+
$memberPreferences = $this->preferenceModel->getMemberPreferences($loggedInMember, $preferences);
4450
$data = [];
4551
foreach ($memberPreferences as $memberPreference) {
4652
$preference = $memberPreference->getPreference();
@@ -50,30 +56,55 @@ public function preferences(
5056
$preferenceForm = $this->createForm(PreferencesType::class, $data, [
5157
'preferences' => $preferences,
5258
]);
53-
$preferenceForm->handleRequest($request);
54-
55-
if ($preferenceForm->isSubmitted() && $preferenceForm->isValid()) {
56-
$data = $preferenceForm->getData();
57-
58-
foreach ($memberPreferences as $memberPreference) {
59-
$preference = $memberPreference->getPreference();
60-
61-
$memberPreference->setValue($data[$preference->getCodename()]);
62-
$entityManager->persist($memberPreference);
63-
}
64-
$entityManager->flush();
65-
66-
return $this->redirectToRoute('members_profile', ['username' => $loggedInMember->getUsername()]);
67-
}
6859

6960
return $this->render('preference/preference.html.twig', [
7061
'member' => $loggedInMember,
71-
'form' => $preferenceForm->createView(),
62+
'form' => $preferenceForm,
7263
'preferences' => $preferences,
7364
'globals_js_json' => $globals->getGlobalsJsAsJson($loggedInMember, $member),
7465
'submenu' => $profileSubmenu->getSubmenu($loggedInMember, $member, [
7566
'active' => 'preferences',
7667
]),
7768
]);
7869
}
70+
71+
#[Route(path: '/members/update/preference', name: 'profile_update_preference', methods: ['POST'], priority: 20)]
72+
public function updatePreference(Request $request): Response
73+
{
74+
$form = $this->createFormBuilder(options: ['csrf_protection' => false])
75+
->add('member', TextType::class)
76+
->add('preference', TextType::class)
77+
->add('value', TextType::class)
78+
->getForm();
79+
80+
$form->submit($request->request->all());
81+
if ($form->isSubmitted() && $form->isValid()) {
82+
$loggedInMember = $this->getUser();
83+
$data = $form->getData();
84+
$memberRepository = $this->entityManager->getRepository(Member::class);
85+
$member = $memberRepository->findOneBy(['username' => $data['member']]);
86+
87+
// Check if user exists and if logged in member is either same or privileged
88+
if ($member === $loggedInMember) {
89+
$preference = $this->entityManager
90+
->getRepository(Preference::class)
91+
->findOneBy(['codename' => $data['preference']])
92+
;
93+
$memberPreference = $member->getMemberPreference($preference);
94+
95+
$value = $data['value'];
96+
if ('false' === $data['value'] || 'true' === $data['value']) {
97+
$values = $preference->getPossibleValues();
98+
$value = 'false' === $data['value'] ? $values[0] : $values[1];
99+
}
100+
101+
$memberPreference->setValue($value);
102+
103+
$this->entityManager->persist($memberPreference);
104+
$this->entityManager->flush();
105+
}
106+
}
107+
108+
return new Response();
109+
}
79110
}

src/Controller/TripController.php

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ class TripController extends AbstractController
2929
use TranslatedFlashTrait;
3030
use TranslatorTrait;
3131

32-
public function __construct(private TripModel $tripModel)
33-
{
32+
public function __construct(
33+
private readonly TripModel $tripModel,
34+
) {
3435
}
3536

3637
#[Route(path: '/trips/{page}', name: 'trips', requirements: ['page' => '\d+'])]

src/Entity/Preference.php

Lines changed: 2 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -157,14 +157,9 @@ public function getDefaultValue()
157157
return $this->defaultValue;
158158
}
159159

160-
/**
161-
* Get possiblevalues.
162-
*
163-
* @return string
164-
*/
165-
public function getPossibleValues()
160+
public function getPossibleValues(): array
166161
{
167-
return $this->possibleValues;
162+
return explode(';', $this->possibleValues);
168163
}
169164

170165
/**

src/Form/PreferencesType.php

Lines changed: 27 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -19,28 +19,34 @@ public function buildForm(FormBuilderInterface $builder, array $options): void
1919
foreach ($preferences as $preference) {
2020
$choices = $this->getChoices($preference);
2121
if (2 === \count($choices)) {
22-
// Create radio buttons
23-
$fieldOptions = [
24-
'expanded' => true,
25-
];
22+
$builder
23+
->add($preference->getCodename(), SwitchType::class, [
24+
'label' => strtolower($preference->getCodename()),
25+
'help' => strtolower($preference->getCodedescription()),
26+
'help_html' => true,
27+
'choices' => $choices,
28+
'default' => $preference->getDefaultValue(),
29+
])
30+
;
2631
} else {
27-
$fieldOptions = [
28-
'expanded' => false,
29-
];
32+
$builder
33+
->add($preference->getCodename(), ChoiceType::class, [
34+
'attr' => [
35+
'class' => 'preference',
36+
],
37+
'label' => strtolower($preference->getCodename()),
38+
'help' => strtolower($preference->getCodedescription()),
39+
'expanded' => false,
40+
'help_html' => true,
41+
'choices' => $choices,
42+
'multiple' => false,
43+
'required' => true,
44+
'constraints' => [
45+
new NotBlank(),
46+
],
47+
])
48+
;
3049
}
31-
$builder
32-
->add($preference->getCodename(), ChoiceType::class, array_merge($fieldOptions, [
33-
'label' => strtolower($preference->getCodename()),
34-
'help' => strtolower($preference->getCodedescription()),
35-
'help_html' => true,
36-
'choices' => $choices,
37-
'multiple' => false,
38-
'required' => true,
39-
'constraints' => [
40-
new NotBlank(),
41-
],
42-
]))
43-
;
4450
}
4551
}
4652

@@ -57,7 +63,7 @@ public function configureOptions(OptionsResolver $resolver): void
5763

5864
private function getChoices(Preference $preference): array
5965
{
60-
$possibleValues = explode(';', $preference->getPossibleValues());
66+
$possibleValues = $preference->getPossibleValues();
6167
$values = [];
6268
foreach ($possibleValues as $value) {
6369
$values[strtolower($preference->getCodename() . $value)] = $value;

0 commit comments

Comments
 (0)