Skip to content

Commit

Permalink
Merge pull request #15 from onshopVN/feature-notification
Browse files Browse the repository at this point in the history
Feature notification
  • Loading branch information
ndquocphong authored Aug 26, 2019
2 parents 5de4cfa + 539d2f2 commit ceffbbc
Show file tree
Hide file tree
Showing 8 changed files with 559 additions and 1 deletion.
102 changes: 102 additions & 0 deletions app/Customize/Controller/Admin/NotificationController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<?php
namespace Customize\Controller\Admin;

use Sensio\Bundle\FrameworkExtraBundle\Configuration\Template;
use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;
use Symfony\Component\HttpFoundation\Request;
use Customize\Service\HttpClient;
use Eccube\Repository\BaseInfoRepository;
use Eccube\Entity\BaseInfo;

class NotificationController extends \Eccube\Controller\AbstractController
{
/**
* @var BaseInfo
*/
protected $baseInfo;

/**
* @var HttpClient
*/
protected $httpClient;

/**
* NotificationController constructor.
* @param BaseInfoRepository $baseInfoRepository
* @param HttpClient $httpClient
* @throws \Exception
*/
public function __construct(
BaseInfoRepository $baseInfoRepository,
HttpClient $httpClient
) {
$this->baseInfo = $baseInfoRepository->get();
$this->httpClient = $httpClient;
}

/**
*
* @Route("/%eccube_admin_route%/notification/ajax", name="customize_admin_notification_ajax")
*
* @param Request $request
* @return JsonResponse
*/
public function ajax(Request $request)
{
$endpoint = $this->baseInfo->getOsStoreApiEndpoint() . '/api/v1/notifications';
$headers = [
'Content-Type: application/json',
'Authorization: Bearer '. $this->baseInfo->getOsStoreAuthToken()
];

$queryParams = [];
$targetId = $request->get('targetId', 0);
if ($targetId) {
$queryParams['targetId'] = $targetId;
}
$targetEntity = $request->get('targetEntity', 'frontend_register');
if ($targetEntity) {
$queryParams['targetEntity'] = $targetEntity;
}

$pageNum = $request->get('pageNum', 0);
if ($pageNum) {
$queryParams['pageNum'] = $pageNum;
}

$pageSize = $request->get('pageSize', 10);
if ($pageSize) {
$queryParams['pageSize'] = $pageSize;
}

if ($queryParams) {
$endpoint .= '?' . http_build_query($queryParams);
}

$result = $this->httpClient->request($endpoint, $headers);

return new JsonResponse($result, 200, [], true);
}

/**
* @Route("/%eccube_admin_route%/notification/ajax/read", name="customize_admin_notification_ajax_read", methods={"PUT"})
*
* @param Request $request
* @return JsonResponse
*/
public function ajaxRead(Request $request)
{
$endpoint = $this->baseInfo->getOsStoreApiEndpoint() . '/api/v1/notifications/' . $request->get('id');
$headers = [
'Content-Type: application/json',
'Authorization: Bearer '. $this->baseInfo->getOsStoreAuthToken()
];
$data = [
'readAt' => 'now'
];
$result = $this->httpClient->put($endpoint, $headers, $data);

return new JsonResponse($result, 200, []);
}
}
54 changes: 54 additions & 0 deletions app/Customize/Controller/Admin/OsController.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
<?php
namespace Customize\Controller\Admin;

use Symfony\Component\Routing\Annotation\Route;
use Symfony\Component\HttpFoundation\JsonResponse;

class OsController extends \Eccube\Controller\AbstractController
{
/**
* @var \Eccube\Entity\BaseInfo
*/
protected $baseInfo;

/**
* @var \Customize\Service\HttpClient
*/
protected $httpClient;

/**
* OsController constructor.
* @param \Eccube\Repository\BaseInfoRepository $baseInfoRepository
* @param \Customize\Service\HttpClient $httpClient
* @throws \Exception
*/
public function __construct(
\Eccube\Repository\BaseInfoRepository $baseInfoRepository,
\Customize\Service\HttpClient $httpClient
) {
$this->baseInfo = $baseInfoRepository->get();
$this->httpClient = $httpClient;
}

/**
*
* @Route("/%eccube_admin_route%/os/ajax", name="customize_admin_os_ajax")
*
* @param \Symfony\Component\HttpFoundation\Request $request
* @return JsonResponse
*/
public function ajax(\Symfony\Component\HttpFoundation\Request $request)
{
$endpoint = $this->baseInfo->getOsStoreApiEndpoint() . '/api/v1/me';
$headers = [
'Content-Type: application/json',
'Authorization: Bearer '. $this->baseInfo->getOsStoreAuthToken()
];

$result = $this->httpClient->request($endpoint, $headers);
$result = json_decode($result, true);
$result['currentVersion'] = env('OS_VERSION') ?: \Eccube\Common\Constant::VERSION;

return new JsonResponse($result);
}
}
9 changes: 8 additions & 1 deletion app/Customize/Resource/locale/messages.vi.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -14,4 +14,11 @@ customize.store.version: Phiên bản
customize.store.message.not_found: Không tìm thấy kết quả.
customize.store.message.install_success: Thao tác đã thành công. Bạn vui lòng truy cập _link_ để kích hoạt tiện ích.
customize.store.message.system_error: Đã có lỗi xảy ra. Bạn vui lòng thử lại thao tác vừa thực hiện.
customize.nav.plugin: Quản lý tiện ích
customize.nav.plugin: Quản lý tiện ích
customize.notification.no_items: Bạn chưa nhận được thông báo nào.
customize.notification.current_version: Phiên bản hiện tại
customize.notification.latest_version: Phiên bản phát hành mới nhất
customize.notification.title: Thông báo/Cập nhật
customize.notification.back: ← Quay lại
customize.onshop.account: Tài khoản Onshop
customize.onshop.email: Thư điện tử
201 changes: 201 additions & 0 deletions app/Customize/Resource/template/Admin/index.twig
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,137 @@ file that was distributed with this source code.
});
</script>

<script src="{{ asset('assets/js/vue.min.js', 'customize') }}"></script>
<script src="{{ asset('assets/js/components/pagination.js', 'customize') }}"></script>
<script>
window.osData = {};
const osVueApp = new Vue({
el: '#os-vue-app',
data: {
id: "",
email: "",
currentVersion: "",
latestVersion: "",
notificationUnreadCount: 0
},
methods: {
submit: function() {
let self = this;
$.ajax({
url: "{{ url('customize_admin_os_ajax') }}"
}).done(function(response) {
if (response.hasOwnProperty("email")) {
self.email = response.email;
}
if (response.hasOwnProperty("currentVersion")) {
self.currentVersion = response.currentVersion;
}
if (response.hasOwnProperty("latestVersion")) {
self.latestVersion = response.latestVersion;
}
if (response.hasOwnProperty("id")) {
self.id = response.id;
window.osData = response;
notificationVueApp.$emit("submit", {"targetId": self.id});
}
if (response.hasOwnProperty("notification")) {
self.notificationUnreadCount = response.notification.unreadCount;
self.attach();
}
});
},
attach: function(count) {
let unreadCount = this.notificationUnreadCount;
if (count === "-1") {
this.notificationUnreadCount = unreadCount = unreadCount - 1;
}
if (unreadCount > 0) {
let $el = $("ul.c-mainNavArea__nav > li.c-mainNavArea__navItem:first-child > .c-mainNavArea__navItemTitle");
$el.find(".noti-count").remove();
$el.append($('<span class="noti-count bg-danger text-white">'+ unreadCount +'</span>'));
}
}
},
created: function() {
let self = this;
this.$on("update:notification-count", self.attach);
},
beforeMount: function() {
this.submit();
}
});
const notificationVueApp = new Vue({
el: '#notification-vue-app',
data: {
items: [],
pageSize: 5,
pageNum: 1,
totals: 0,
content: null,
loading: true,
},
methods: {
read: function(item) {
if (item.status !== 'read') {
osVueApp.$emit("update:notification-count", "-1");
item.status = 'read';
$.ajax({
url: "{{ url('customize_admin_notification_ajax_read') }}",
type: "PUT",
data: {
id: item.id
}
}).done(function(response) {
});
}
this.content = item.content;
},
back: function() {
this.content = null;
},
submit: function(data) {
let self = this,
params = {};
if (data && data.hasOwnProperty('number')) {
params.pageNum = data.number;
}
if (data && data.hasOwnProperty("targetId")) {
params.targetId = data.targetId;
}
$.ajax({
url: "{{ url('customize_admin_notification_ajax') }}",
data: Object.assign({
pageSize: self.pageSize,
pageNum: self.pageNum,
targetEntity: "frontend_register",
targetId: 0,
}, params)
}).done(function(response) {
if (response.hasOwnProperty("items")) {
self.items = response.items;
}
if (response.hasOwnProperty("totals")) {
self.totals = response.totals;
}
if (response.hasOwnProperty("pageNum")) {
self.pageNum = response.pageNum;
}
if (response.hasOwnProperty("pageSize")) {
self.pageSize = response.pageSize;
}
});
}
},
created: function() {
let self = this;
this.$on('submit', self.submit);
},
mounted: function() {
$("#notification-vue-app").removeClass('invisible');
}
});
</script>
{% endblock javascript %}

{% block main %}
Expand All @@ -121,6 +252,76 @@ file that was distributed with this source code.
<div class="c-contentsArea__cols">
<div class="c-contentsArea__primaryCol">
<div class="c-primaryCol">
<div class="row">
<div class="col-4 mb-4">
<div id="os-vue-app">
<div class="card rounded border-0 h-100">
<div class="card-header">{{ 'customize.onshop.account'|trans }}</div>
<div class="card-body p-0">
<div class="d-block border border-top-0 border-left-0 border-right-0">
<div class="d-flex p-3 justify-content-between">
<label class="mb-0">{{ 'customize.onshop.email'|trans }}</label>
<p class="mb-0"><strong v-text="email"></strong></p>
</div>
</div>
<div class="d-block border border-top-0 border-left-0 border-right-0">
<div class="d-flex p-3 justify-content-between">
<label class="mb-0">{{ 'customize.notification.current_version'|trans }}</label>
<p class="mb-0"><strong v-text="currentVersion"></strong></p>
</div>
</div>
<div class="d-block border border-top-0 border-left-0 border-right-0">
<div class="d-flex p-3 justify-content-between">
<label class="mb-0">{{ 'customize.notification.latest_version'|trans }}</label>
<p class="mb-0 text-success"><strong v-text="latestVersion"></strong></p>
</div>
</div>
</div>
</div>
</div>
</div>
<div class="col-8 mb-4">
<div id="notification-vue-app" class="onshop-notification invisible" @submit="submit">
<div class="card rounded border-0 h-100">
<div class="card-header"><span class="card-title">{{ 'customize.notification.title'|trans }}</span></div>
<div class="card-body p-0">
<div v-if="items.length > 0">
<div v-show="content === null">
<div class="d-block border border-top-0 border-left-0 border-right-0" v-for="item in items">
<a href="javascript:void(0)" class="py-3 pl-4 pr-5 d-block message-link" :class="item.status === 'read' ? 'read text-muted' : 'unread'" @click.stop.prevent="read(item)">
<div class="row align-items-center">
<div class="col align-middle"><span class="align-middle font-weight-bold" v-text="item.title"></span></div>
</div>
</a>
</div>
</div>
<div v-show="content !== null" class="py-3 pl-4 pr-4">
<div v-html="content"></div>
<button class="btn btn-ec-regular btn-sm mt-4" @click.stop.prevent="back">{{ 'customize.notification.back'|trans }}</button>
</div>
<ui-pagination inline-template :page-size="pageSize" :page-num="pageNum" :totals="totals" :page-range="2" :submit-callback="submit" v-show="content === null">
<ul class="pagination justify-content-center my-3" v-show="isVisible">
<li class="page-item" :class="page.className" :disabled="page.disabled" v-for="page in pages">
<button class="page-link" @click.stop.prevent="submit(page)">
<i v-if="page.showLoading" class="fa fa-circle-notch fa-spin fa-1x fa-fw margin-bottom"></i>
<span v-else v-text="page.number"></span>
</button>
</li>
</ul>
</ui-pagination>
</div>
<div v-else>
<div class="alert alert-info m-3" role="alert">
<i class="fa fa-comment fa-lg mr-2"></i>
<span>{{ 'customize.notification.no_items'|trans }}</span>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

<div class="row">
<div class="col-4 mb-4">
<div id="order-status" class="card rounded border-0 h-100">
Expand Down
Loading

0 comments on commit ceffbbc

Please sign in to comment.