diff --git a/assets/router/index.js b/assets/router/index.js
index 9cdbb48..e1bfe66 100644
--- a/assets/router/index.js
+++ b/assets/router/index.js
@@ -5,6 +5,8 @@ import ListsView from '../vue/views/ListsView.vue'
import ListSubscribersView from '../vue/views/ListSubscribersView.vue'
import CampaignsView from '../vue/views/CampaignsView.vue'
import CampaignEditView from '../vue/views/CampaignEditView.vue'
+import TemplatesView from '../vue/views/TemplatesView.vue'
+import TemplateEditView from '../vue/views/TemplateEditView.vue'
export const router = createRouter({
history: createWebHistory(),
@@ -13,6 +15,9 @@ export const router = createRouter({
{ path: '/subscribers', name: 'subscribers', component: SubscribersView, meta: { title: 'Subscribers' } },
{ path: '/lists', name: 'lists', component: ListsView, meta: { title: 'Lists' } },
{ path: '/campaigns', name: 'campaigns', component: CampaignsView, meta: { title: 'Campaigns' } },
+ { path: '/templates', name: 'templates', component: TemplatesView, meta: { title: 'Templates' } },
+ { path: '/templates/create', name: 'template-create', component: TemplateEditView, meta: { title: 'Create Template' } },
+ { path: '/templates/:templateId/edit', name: 'template-edit', component: TemplateEditView, meta: { title: 'Edit Template' } },
{ path: '/campaigns/create', name: 'campaign-create', component: CampaignEditView, meta: { title: 'Create Campaign' } },
{ path: '/campaigns/:campaignId/edit', name: 'campaign-edit', component: CampaignEditView, meta: { title: 'Edit Campaign' } },
{ path: '/lists/:listId/subscribers', name: 'list-subscribers', component: ListSubscribersView, meta: { title: 'List Subscribers' } },
diff --git a/assets/vue/components/base/BaseIcon.vue b/assets/vue/components/base/BaseIcon.vue
index c427505..2955106 100644
--- a/assets/vue/components/base/BaseIcon.vue
+++ b/assets/vue/components/base/BaseIcon.vue
@@ -24,7 +24,7 @@ const props = defineProps({
const icons = {
users: ``,
- addUser: ``,
+ addUser: ``,
removeUser: ``,
@@ -91,6 +91,10 @@ const icons = {
plugin: ``,
chevronDown: ``,
+
+ pause: ``,
+
+ start: ``,
};
const svg = computed(() => icons[props.name] || "");
diff --git a/assets/vue/components/campaigns/CampaignDirectory.vue b/assets/vue/components/campaigns/CampaignDirectory.vue
index 7683a3c..91bedec 100644
--- a/assets/vue/components/campaigns/CampaignDirectory.vue
+++ b/assets/vue/components/campaigns/CampaignDirectory.vue
@@ -90,54 +90,60 @@
@@ -224,54 +230,60 @@
@@ -333,6 +345,7 @@ import { computed, onMounted, ref, watch } from 'vue'
import { useRoute, useRouter } from 'vue-router'
import { campaignClient, fetchAllLists, listMessagesClient, statisticsClient } from '../../api'
import ViewCampaignModal from "./ViewCampaignModal.vue";
+import BaseIcon from '../base/BaseIcon.vue'
const pageSize = 5
const route = useRoute()
diff --git a/assets/vue/components/dashboard/QuickActionsCard.vue b/assets/vue/components/dashboard/QuickActionsCard.vue
index 51e5419..ba403f4 100644
--- a/assets/vue/components/dashboard/QuickActionsCard.vue
+++ b/assets/vue/components/dashboard/QuickActionsCard.vue
@@ -81,9 +81,9 @@
import BaseCard from '../../components/base/BaseCard.vue'
const quickActions = [
- { id: 'campaign', label: 'New Campaign', href: '/campaigns' },
+ { id: 'campaign', label: 'New Campaign', href: '/campaigns/create' },
{ id: 'subscribers', label: 'Add Subscribers', href: '/subscribers' },
- { id: 'import', label: 'Import List', href: '/subscribers' },
+ { id: 'import', label: 'Import List', href: '/lists' },
{ id: 'templates', label: 'Manage Templates', href: '/templates' },
]
diff --git a/assets/vue/components/lists/ListDirectory.vue b/assets/vue/components/lists/ListDirectory.vue
index 5bf294b..082f47b 100644
--- a/assets/vue/components/lists/ListDirectory.vue
+++ b/assets/vue/components/lists/ListDirectory.vue
@@ -140,41 +140,46 @@
diff --git a/assets/vue/components/subscribers/SubscriberDirectory.vue b/assets/vue/components/subscribers/SubscriberDirectory.vue
index 35b427f..a53da9e 100644
--- a/assets/vue/components/subscribers/SubscriberDirectory.vue
+++ b/assets/vue/components/subscribers/SubscriberDirectory.vue
@@ -2,7 +2,7 @@
-
Subscriber Directory
+
Subscribers
diff --git a/assets/vue/components/subscribers/SubscriberTable.vue b/assets/vue/components/subscribers/SubscriberTable.vue
index 3fae562..b4919c4 100644
--- a/assets/vue/components/subscribers/SubscriberTable.vue
+++ b/assets/vue/components/subscribers/SubscriberTable.vue
@@ -9,7 +9,7 @@
Status |
Lists |
Created |
-
|
+
Actions |
@@ -48,10 +48,12 @@
|
@@ -69,13 +71,7 @@
{{ subscriber.email.split('@')[0] }}
-
-
+
blacklisted
+
diff --git a/assets/vue/components/templates/TemplateLibrary.vue b/assets/vue/components/templates/TemplateLibrary.vue
new file mode 100644
index 0000000..7f623e3
--- /dev/null
+++ b/assets/vue/components/templates/TemplateLibrary.vue
@@ -0,0 +1,333 @@
+
+
+
+ Templates
+
+
+
+
+
+
+
+
+ Loading templates...
+
+
+
+ {{ errorMessage }}
+
+
+
+ No templates found.
+
+
+
+
+
+
![]()
+
+
+
+
{{ templateItem.title || `Template #${templateItem.id}` }}
+
+ {{ getTemplateType(templateItem) }}
+
+
+
+ ID {{ templateItem.id }}
+ Order {{ templateItem.listOrder ?? '-' }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/assets/vue/views/ListSubscribersView.vue b/assets/vue/views/ListSubscribersView.vue
index f51b621..762483f 100644
--- a/assets/vue/views/ListSubscribersView.vue
+++ b/assets/vue/views/ListSubscribersView.vue
@@ -42,10 +42,11 @@
Selected: {{ selectedSubscribers.length }}
@@ -64,19 +65,21 @@
@@ -144,10 +147,11 @@
|
@@ -201,10 +205,11 @@
#{{ subscriber.id }} ยท {{formatDate(subscriber.createdAt) }}
@@ -255,6 +260,7 @@ import {computed, onMounted, ref, watch, watchEffect} from 'vue'
import {useRoute} from 'vue-router'
import AdminLayout from '../layouts/AdminLayout.vue'
import ListSubscribersExportPanel from '../components/lists/ListSubscribersExportPanel.vue'
+import BaseIcon from '../components/base/BaseIcon.vue'
import client, {subscriptionClient} from '../api'
const route = useRoute()
diff --git a/assets/vue/views/TemplateEditView.vue b/assets/vue/views/TemplateEditView.vue
new file mode 100644
index 0000000..7e2b1ba
--- /dev/null
+++ b/assets/vue/views/TemplateEditView.vue
@@ -0,0 +1,308 @@
+
+
+
+
+
+
+
Template
+
{{ pageTitle }}
+
+
+
+ Back to Templates
+
+
+
+
+
+ Loading template...
+
+
+
+ {{ loadError }}
+
+
+
+
+
+
+
+
diff --git a/assets/vue/views/TemplatesView.vue b/assets/vue/views/TemplatesView.vue
new file mode 100644
index 0000000..06ddeda
--- /dev/null
+++ b/assets/vue/views/TemplatesView.vue
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
+
+
diff --git a/package.json b/package.json
index e329355..43f74e5 100644
--- a/package.json
+++ b/package.json
@@ -25,7 +25,7 @@
},
"dependencies": {
"@ckeditor/ckeditor5-vue": "^7.4.0",
- "@tatevikgr/rest-api-client": "^2.0.5",
+ "@tatevikgr/rest-api-client": "^2.1.0",
"apexcharts": "^5.10.4",
"ckeditor5": "^48.0.0",
"vue": "^3.5.16",
diff --git a/src/Controller/TemplatesController.php b/src/Controller/TemplatesController.php
new file mode 100644
index 0000000..5d0cb29
--- /dev/null
+++ b/src/Controller/TemplatesController.php
@@ -0,0 +1,44 @@
+render('@PhpListFrontend/spa.html.twig', [
+ 'page' => 'Templates',
+ 'api_token' => $request->getSession()->get('auth_token'),
+ 'api_base_url' => $this->getParameter('api_base_url'),
+ ]);
+ }
+
+ #[Route('/create', name: 'create', methods: ['GET'])]
+ public function create(Request $request): Response
+ {
+ return $this->render('@PhpListFrontend/spa.html.twig', [
+ 'page' => 'Create Template',
+ 'api_token' => $request->getSession()->get('auth_token'),
+ 'api_base_url' => $this->getParameter('api_base_url'),
+ ]);
+ }
+
+ #[Route('/{templateId}/edit', name: 'edit', methods: ['GET'])]
+ public function edit(Request $request, int $templateId): Response
+ {
+ return $this->render('@PhpListFrontend/spa.html.twig', [
+ 'page' => sprintf('Edit Template #%d', $templateId),
+ 'api_token' => $request->getSession()->get('auth_token'),
+ 'api_base_url' => $this->getParameter('api_base_url'),
+ ]);
+ }
+}
diff --git a/templates/auth/login.html.twig b/templates/auth/login.html.twig
index d927e01..e32f82c 100644
--- a/templates/auth/login.html.twig
+++ b/templates/auth/login.html.twig
@@ -41,7 +41,7 @@
-
diff --git a/yarn.lock b/yarn.lock
index 4a31d56..7e07567 100644
--- a/yarn.lock
+++ b/yarn.lock
@@ -2119,10 +2119,10 @@
postcss "^8.5.6"
tailwindcss "4.2.1"
-"@tatevikgr/rest-api-client@^2.0.5":
- version "2.0.5"
- resolved "https://registry.yarnpkg.com/@tatevikgr/rest-api-client/-/rest-api-client-2.0.5.tgz#790075dc66fcbe90b6c5e823d23fd2c72b34c925"
- integrity sha512-Nc2YVWKIP4CD+TEXxkBtko/eQWtGT2zTW8VShrHHQd5e7+8ZtRs9/DOr5gka/roOEE+srU0KZDRtm91c+SYnVw==
+"@tatevikgr/rest-api-client@^2.1.0":
+ version "2.1.0"
+ resolved "https://registry.yarnpkg.com/@tatevikgr/rest-api-client/-/rest-api-client-2.1.0.tgz#9b0f519378fd9301e7fdb8124f11d3bc662e791f"
+ integrity sha512-Gp0L67gMMmZK12McgBMxOb8+PtDr0nnZC1B1aO2aGTz3nz3lQ7GvwQpVFNTbq0pQWuDG4rxWS1tJM3nttgV3oQ==
dependencies:
axios "^1.6.0"