diff --git a/.idea/php.xml b/.idea/php.xml
index 66d6fb8..214f408 100644
--- a/.idea/php.xml
+++ b/.idea/php.xml
@@ -13,6 +13,7 @@
+
diff --git a/assets/styles/app.scss b/assets/styles/app.scss
index 1f41fc1..fff5ff0 100644
--- a/assets/styles/app.scss
+++ b/assets/styles/app.scss
@@ -359,20 +359,40 @@ ul.credit {
.app-overview-dashboard {
display: grid;
gap: 1rem;
- grid-template:
- "hello-text" auto
- "announcements" auto
- "weekly-metrics" auto
- "historic-statistics" auto
- "leaderboard" auto;
-
- @media (min-width: 1440px) {
+
+ &-criterion-reference {
+ grid-template:
+ "hello-text" auto
+ "announcements" auto
+ "weekly-metrics" auto
+ "historic-statistics" auto
+ "leaderboard" auto;
+
+ @media (min-width: 1440px) {
+ grid-template:
+ "hello-text hello-text hello-text hello-text" auto
+ "announcements announcements announcements announcements" auto
+ "weekly-metrics weekly-metrics leaderboard leaderboard" 1fr
+ "historic-statistics historic-statistics leaderboard leaderboard" 1fr;
+ grid-template-columns: 2fr 2fr 1fr 1fr;
+ }
+ }
+
+ &-self-reference {
grid-template:
- "hello-text hello-text hello-text hello-text" auto
- "announcements announcements announcements announcements" auto
- "weekly-metrics weekly-metrics leaderboard leaderboard" 1fr
- "historic-statistics historic-statistics leaderboard leaderboard" 1fr;
- grid-template-columns: 2fr 2fr 1fr 1fr;
+ "hello-text" auto
+ "announcements" auto
+ "weekly-metrics" auto
+ "historic-statistics" auto;
+
+ @media (min-width: 1440px) {
+ grid-template:
+ "hello-text hello-text hello-text hello-text" auto
+ "announcements announcements announcements announcements" auto
+ "weekly-metrics weekly-metrics weekly-metrics weekly-metrics" 1fr
+ "historic-statistics historic-statistics historic-statistics historic-statistics" 1fr;
+ grid-template-columns: 1fr 1fr 1fr 1fr;
+ }
}
&__hello-text {
diff --git a/migrations/Version20241230103024.php b/migrations/Version20241230103024.php
new file mode 100644
index 0000000..58a1238
--- /dev/null
+++ b/migrations/Version20241230103024.php
@@ -0,0 +1,35 @@
+addSql(<<<'SQL'
+ ALTER TABLE "group" ADD layout VARCHAR(255) DEFAULT NULL
+ SQL);
+ }
+
+ public function down(Schema $schema): void
+ {
+ // this down() migration is auto-generated, please modify it to your needs
+ $this->addSql(<<<'SQL'
+ ALTER TABLE "group" DROP layout
+ SQL);
+ }
+}
diff --git a/src/Controller/Admin/GroupCrudController.php b/src/Controller/Admin/GroupCrudController.php
index f8e94a6..df32999 100644
--- a/src/Controller/Admin/GroupCrudController.php
+++ b/src/Controller/Admin/GroupCrudController.php
@@ -6,11 +6,14 @@
use App\Entity\Group;
use EasyCorp\Bundle\EasyAdminBundle\Controller\AbstractCrudController;
+use EasyCorp\Bundle\EasyAdminBundle\Field\ChoiceField;
use EasyCorp\Bundle\EasyAdminBundle\Field\DateTimeField;
use EasyCorp\Bundle\EasyAdminBundle\Field\IdField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextEditorField;
use EasyCorp\Bundle\EasyAdminBundle\Field\TextField;
+use function Symfony\Component\Translation\t;
+
class GroupCrudController extends AbstractCrudController
{
public static function getEntityFqcn(): string
@@ -20,10 +23,26 @@ public static function getEntityFqcn(): string
public function configureFields(string $pageName): iterable
{
+ $availableLayouts = glob(__DIR__.'/../../../templates/overview/layout/*.html.twig');
+ if (false === $availableLayouts) {
+ $availableLayouts = [];
+ }
+
+ $availableLayouts = array_map(static fn ($path) => pathinfo($path, PATHINFO_BASENAME), $availableLayouts);
+ if (0 === \count($availableLayouts)) {
+ $availableLayouts = ['default.html.twig'];
+ }
+
+ // trim the .html.twig extension
+ $availableLayouts = array_map(static fn ($layout) => substr($layout, 0, -10), $availableLayouts);
+
return [
IdField::new('id')->hideOnForm(),
TextField::new('name', 'Name'),
TextEditorField::new('description', 'Description'),
+ ChoiceField::new('layout', 'Layout')
+ ->setChoices(array_combine($availableLayouts, $availableLayouts))
+ ->setHelp(t('admin.group.layout.help')),
DateTimeField::new('created_at', 'Created at')->hideOnForm(),
DateTimeField::new('updated_at', 'Updated at')->hideOnForm(),
];
diff --git a/src/Controller/Admin/UserCrudController.php b/src/Controller/Admin/UserCrudController.php
index a6be619..57d07a4 100644
--- a/src/Controller/Admin/UserCrudController.php
+++ b/src/Controller/Admin/UserCrudController.php
@@ -54,7 +54,7 @@ public function configureFields(string $pageName): iterable
AssociationField::new('group', 'Group'),
DateTimeField::new('created_at', 'Created at')->hideOnForm(),
DateTimeField::new('updated_at', 'Updated at')->hideOnForm(),
- DateTimeField::new('last_login_at', 'Last login at'),
+ DateTimeField::new('last_login_at', 'Last login at')->hideOnForm(),
];
}
diff --git a/src/Controller/OverviewController.php b/src/Controller/OverviewController.php
index 5f1e2a2..4244fc1 100644
--- a/src/Controller/OverviewController.php
+++ b/src/Controller/OverviewController.php
@@ -4,17 +4,24 @@
namespace App\Controller;
+use App\Entity\User;
use App\Repository\AnnouncementRepository;
use Symfony\Bundle\FrameworkBundle\Controller\AbstractController;
use Symfony\Component\HttpFoundation\Response;
use Symfony\Component\Routing\Attribute\Route;
+use Symfony\Component\Security\Http\Attribute\CurrentUser;
class OverviewController extends AbstractController
{
#[Route('/overview', name: 'app_overview')]
- public function index(): Response
+ public function index(#[CurrentUser] User $user): Response
{
- return $this->render('overview/index.html.twig');
+ $layoutName = $user->getGroup()?->getLayout() ?? 'default';
+ $mainContent = $this->renderView("overview/layout/{$layoutName}.html.twig");
+
+ return $this->render('overview/index.html.twig', [
+ 'mainContent' => $mainContent,
+ ]);
}
#[Route('/overview/announcements', name: 'app_overview_announcements')]
diff --git a/src/Entity/Group.php b/src/Entity/Group.php
index 13b3c72..7ff1d30 100644
--- a/src/Entity/Group.php
+++ b/src/Entity/Group.php
@@ -34,6 +34,9 @@ class Group
#[ORM\OneToMany(targetEntity: User::class, mappedBy: 'group')]
private Collection $users;
+ #[ORM\Column(length: 255, nullable: true)]
+ private ?string $layout = null;
+
public function __construct()
{
$this->users = new ArrayCollection();
@@ -109,4 +112,16 @@ public function removeUser(User $user): static
return $this;
}
+
+ public function getLayout(): ?string
+ {
+ return $this->layout;
+ }
+
+ public function setLayout(?string $layout): static
+ {
+ $this->layout = $layout;
+
+ return $this;
+ }
}
diff --git a/templates/overview/index.html.twig b/templates/overview/index.html.twig
index c3a336a..755bbf2 100644
--- a/templates/overview/index.html.twig
+++ b/templates/overview/index.html.twig
@@ -4,53 +4,5 @@
{% block title %}學習概況{% endblock %}
{% block app %}
-
-
- 哈囉,{{ app.user.name }} 👋
- 這些是你最近的表現 ↓
-
-
-
-
-
-
-
-
-
-
+{{ mainContent|raw }}
{% endblock %}
diff --git a/templates/overview/layout/default.html.twig b/templates/overview/layout/default.html.twig
new file mode 100644
index 0000000..d4ea8ba
--- /dev/null
+++ b/templates/overview/layout/default.html.twig
@@ -0,0 +1,49 @@
+
+
+ 哈囉,{{ app.user.name }} 👋
+ 這些是你最近的表現 ↓
+
+
+
+
+
+
+
+
+
+
diff --git a/templates/overview/layout/self-reference.html.twig b/templates/overview/layout/self-reference.html.twig
new file mode 100644
index 0000000..a67da87
--- /dev/null
+++ b/templates/overview/layout/self-reference.html.twig
@@ -0,0 +1,44 @@
+
+
+ 哈囉,{{ app.user.name }} 👋
+ 這些是你最近的表現 ↓
+
+
+
+
+
+
+
+
diff --git a/translations/messages.en_US.yaml b/translations/messages.en_US.yaml
index 465b4da..c65e71d 100644
--- a/translations/messages.en_US.yaml
+++ b/translations/messages.en_US.yaml
@@ -6,3 +6,10 @@ challenge:
column-different: The column names differ; please compare and modify according to the correct answer.
row-different: The %row% row you answered is different from the correct answer.
row-unmatched: The number of returned rows does not match the correct answer (the correct answer has %expected% rows, while you answered %actual% rows).
+
+admin:
+ group:
+ layout:
+ help: >-
+ Layout name. Leave blank to use the default layout.
+ You can create your own layout in the templates/overview/layout
directory in the code.
diff --git a/translations/messages.zh_TW.yaml b/translations/messages.zh_TW.yaml
index 7a026ff..07297a0 100644
--- a/translations/messages.zh_TW.yaml
+++ b/translations/messages.zh_TW.yaml
@@ -72,6 +72,7 @@ Last login at: 最後登入時間
Statistics: 統計資料
Completed Questions: 完成題數
Experience Points: 經驗值
+Layout: 佈局
result_presenter.tabs.result: 執行結果
result_presenter.tabs.answer: 正確答案
@@ -191,3 +192,10 @@ email-kind:
transactional: 通知型信件
marketing: 行銷型信件
test: 測試用信件
+
+admin:
+ group:
+ layout:
+ help: >-
+ 版面名稱。留空代表使用預設版面。
+ 可以在程式碼的 templates/overview/layout
目錄製作自己想要的版面。