From c62d0d1d9fe96820e6bef666bdad3201c7ec4090 Mon Sep 17 00:00:00 2001 From: Julio Montoya Date: Mon, 14 Sep 2020 13:37:52 +0200 Subject: [PATCH] Internal: Add lib to handle flash messages: vue-toastification --- assets/vue/App.vue | 5 +- assets/vue/components/Snackbar.vue | 24 ++++----- assets/vue/main.js | 9 ++++ assets/vue/mixins/NotificationMixin.js | 50 ++++++++++++++++--- package.json | 1 + public/main/admin/careers.php | 9 ++-- public/main/inc/global.inc.php | 18 ++++++- public/main/inc/lib/display.lib.php | 24 +++++---- .../views/Layout/base-layout.html.twig | 6 +-- yarn.lock | 5 ++ 10 files changed, 107 insertions(+), 44 deletions(-) diff --git a/assets/vue/App.vue b/assets/vue/App.vue index f294fdae29..10c115acc9 100644 --- a/assets/vue/App.vue +++ b/assets/vue/App.vue @@ -18,7 +18,7 @@ - +
- - {{ text }} - - - +
+ +
@@ -36,14 +28,18 @@ import { mapFields } from 'vuex-map-fields'; export default { - computed: { + props: { + message: String, + }, + /*computed: { ...mapFields('notifications', ['color', 'show', 'subText', 'text', 'timeout']) }, - methods: { + close() { this.show = false; } - } + }*/ + }; diff --git a/assets/vue/main.js b/assets/vue/main.js index d46ac74443..eea9d578f5 100644 --- a/assets/vue/main.js +++ b/assets/vue/main.js @@ -40,6 +40,15 @@ Vue.use(Vuelidate); //Vue.use(VueApollo); Vue.use(require('vue-moment')); +import Toast from 'vue-toastification'; +import 'vue-toastification/dist/index.css'; + +Vue.use(Toast, { + transition: 'Vue-Toastification__bounce', + maxToasts: 20, + newestOnTop: true +}); + /*const apolloProvider = new VueApollo({ defaultClient: apolloClient, });*/ diff --git a/assets/vue/mixins/NotificationMixin.js b/assets/vue/mixins/NotificationMixin.js index 156e6ce2b9..5845267013 100644 --- a/assets/vue/mixins/NotificationMixin.js +++ b/assets/vue/mixins/NotificationMixin.js @@ -1,4 +1,5 @@ import { mapFields } from 'vuex-map-fields'; +import Component from "../components/Snackbar.vue"; export default { computed: { @@ -7,19 +8,52 @@ export default { methods: { cleanState() { - setTimeout(() => { - this.show = false; - }, this.timeout); + + /*setTimeout(() => { + this.show = false; + }, this.timeout + );*/ }, showError(error) { //this.showMessage(error, 'danger'); }, - showMessage(message, color = 'success') { - this.show = true; - this.color = color; + showMessage(message, type = 'success') { + const content = { + // Your component or JSX template + component: Component, + + // Props are just regular props, but these won't be reactive + props: { + message: message + }, + + // Listeners will listen to and execute on event emission + listeners: { + //click: () => console.log("Clicked!"), + //myEvent: myEventHandler + } + }; + this.$toast(content, { + type: type, + position: 'top-right', + timeout: 10000, // 10 seconds + closeOnClick: true, + pauseOnFocusLoss: true, + pauseOnHover: true, + draggable: true, + draggablePercent: 0.6, + showCloseButtonOnHover: false, + hideProgressBar: true, + closeButton: "button", + icon: true, + rtl: false + }); + + /*this.show = true; + this.color = color; if (typeof message === 'string') { this.text = message; this.cleanState(); @@ -31,7 +65,9 @@ export default { if (message.response) this.subText = message.response.data.message; - this.cleanState(); + this.cleanState();*/ + + } } }; diff --git a/package.json b/package.json index 205a8366d7..6324d8dd02 100644 --- a/package.json +++ b/package.json @@ -80,6 +80,7 @@ "vue-router": "^3.1.6", "vue-sidebar-menu": "^4.7.1", "vue-template-compiler": "^2.6.10", + "vue-toastification": "^1.7.7", "vuelidate": "^0.7.5", "vuetify": "^2.2.27", "vuex": "^3.3.0", diff --git a/public/main/admin/careers.php b/public/main/admin/careers.php index 34afe1d825..1bd585f26b 100644 --- a/public/main/admin/careers.php +++ b/public/main/admin/careers.php @@ -1,7 +1,6 @@ 'careers.php', 'name' => get_lang('Careers')]; $tool_name = get_lang('Add'); -} elseif ('edit' == $action) { +} elseif ('edit' === $action) { $interbreadcrumb[] = ['url' => 'careers.php', 'name' => get_lang('Careers')]; $interbreadcrumb[] = ['url' => '#', 'name' => get_lang('Edit')]; $tool_name = get_lang('Edit'); @@ -97,7 +96,6 @@ if (api_is_platform_admin()) { $career = new Career(); $content = ''; - $listUrl = api_get_self(); // Action handling: Add @@ -110,7 +108,6 @@ switch ($action) { ) { api_not_allowed(); } - Session::write('notebook_view', 'creation_date'); $url = api_get_self().'?action='.Security::remove_XSS($_GET['action']); $form = $career->return_form($url, 'add'); diff --git a/public/main/inc/global.inc.php b/public/main/inc/global.inc.php index f82cbe3c37..c9345c73e8 100644 --- a/public/main/inc/global.inc.php +++ b/public/main/inc/global.inc.php @@ -1,4 +1,5 @@ getBaseUrl(); $kernel->boot(); - $container = $kernel->getContainer(); $router = $container->get('router'); + /** @var \Symfony\Component\HttpFoundation\Session\Flash\FlashBag $flashBag */ + $flashBag = $container->get('session')->getFlashBag(); + $saveFlashBag = null; + if (!empty($flashBag->keys())) { + $saveFlashBag = $flashBag->all(); + } + $context = $router->getContext(); $router->setContext($context); @@ -72,6 +78,14 @@ try { // Symfony uses request_stack now $container->get('request_stack')->push($request); + if (!empty($saveFlashBag)) { + foreach ($saveFlashBag as $type => $messageList) { + foreach ($messageList as $message) { + Container::getSession()->getFlashBag()->add($type, $message); + } + } + } + // Connect Chamilo with the Symfony container // Container::setContainer($container); // Container::setLegacyServices($container); diff --git a/public/main/inc/lib/display.lib.php b/public/main/inc/lib/display.lib.php index 5cff6f25bc..703d33df84 100644 --- a/public/main/inc/lib/display.lib.php +++ b/public/main/inc/lib/display.lib.php @@ -124,9 +124,9 @@ class Display $params['legacy_javascript'] = $htmlHeadXtra; $params['legacy_breadcrumb'] = $interbreadcrumb; - $flash = Display::getFlashToString(); - Display::cleanFlashMessages(); - $params['flash_messages'] = $flash; + $flash = self::getFlashToString(); + self::cleanFlashMessages(); + //$params['flash_messages'] = $flash; Template::setVueParams($params); $content = Container::getTemplating()->render($tpl, $params); @@ -2401,19 +2401,23 @@ class Display } /** - * Adds a message in the queue. + * Adds a legacy message in the queue. * * @param string $message */ public static function addFlash($message) { - $messages = Session::read('flash_messages'); - if (empty($messages)) { - $messages[] = $message; - } else { - array_push($messages, $message); + // Detect type of message. + $parts = preg_match('/alert-([a-z]*)/', $message, $matches); + $type = 'primary'; + if ($parts && isset($matches[1]) && $matches[1]) { + $type = $matches[1]; + } + // Detect legacy content of message. + $result = preg_match('/(.*?)\<\/div>/s', $message, $matches); + if ($result && isset($matches[2])) { + Container::getSession()->getFlashBag()->add($type, $matches[2]); } - Session::write('flash_messages', $messages); } /** diff --git a/src/CoreBundle/Resources/views/Layout/base-layout.html.twig b/src/CoreBundle/Resources/views/Layout/base-layout.html.twig index a371d4e47c..118c9f3bd9 100644 --- a/src/CoreBundle/Resources/views/Layout/base-layout.html.twig +++ b/src/CoreBundle/Resources/views/Layout/base-layout.html.twig @@ -18,9 +18,9 @@ data-in-course="{{ course ? 'true' : 'false' }}" data-course-code="{{ course ? course.code : '' }}" data-session-id="{{ session ? session.id : '' }}" - {% if legacy_breadcrumb is defined %} - data-breadcrumb="{{ legacy_breadcrumb | json_encode() }}" - {% endif %} +{# {% if legacy_breadcrumb is defined %}#} +{# data-breadcrumb="{{ legacy_breadcrumb | json_encode() }}"#} +{# {% endif %}#} > {% block chamilo_wrap %} diff --git a/yarn.lock b/yarn.lock index 4622f16a50..df6357a6f5 100644 --- a/yarn.lock +++ b/yarn.lock @@ -14536,6 +14536,11 @@ vue-template-es2015-compiler@^1.9.0: resolved "https://registry.yarnpkg.com/vue-template-es2015-compiler/-/vue-template-es2015-compiler-1.9.1.tgz#1ee3bc9a16ecbf5118be334bb15f9c46f82f5825" integrity sha512-4gDntzrifFnCEvyoO8PqyJDmguXgVPxKiIxrBKjIowvL9l+N66196+72XVYR8BBf1Uv1Fgt3bGevJ+sEmxfZzw== +vue-toastification@^1.7.7: + version "1.7.7" + resolved "https://registry.yarnpkg.com/vue-toastification/-/vue-toastification-1.7.7.tgz#bbc431a9a9c73f565d42c1d3e5239d96e065f348" + integrity sha512-SWYy6ycw6D91nBWPoaJfwIAsmUsk0pZMZ3JjCgOdozEW/QyaVbX+XL0Z2iskNDCOqwA/znIhhBN/H10eURpxkQ== + vue@^2.5.21, vue@^2.6.11, vue@^2.6.12: version "2.6.12" resolved "https://registry.yarnpkg.com/vue/-/vue-2.6.12.tgz#f5ebd4fa6bd2869403e29a896aed4904456c9123"