diff --git a/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php b/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php index e76c77989..1eff65bcd 100644 --- a/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php +++ b/src/opnsense/mvc/app/controllers/OPNsense/Core/Api/DashboardController.php @@ -196,4 +196,27 @@ class DashboardController extends ApiControllerBase return $result; } + + public function productInfoFeedAction() + { + $result = ['items' => []]; + $ch = curl_init(); + curl_setopt($ch, CURLOPT_URL, 'https://forum.opnsense.org/index.php?board=11.0&action=.xml;limit=5;type=rss2'); + curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); + $output = curl_exec($ch); + curl_close($ch); + $payload = simplexml_load_string($output); + foreach ($payload->channel->children() as $key => $node) { + if ($key == 'item') { + $result['items'][] = [ + 'title' => (string)$node->title, + 'description' => (string)$node->description, + 'link' => (string)$node->link, + 'pubDate' => (string)$node->pubDate, + 'guid' => (string)$node->guid + ]; + } + } + return $result; + } } diff --git a/src/opnsense/www/js/widgets/Announcements.js b/src/opnsense/www/js/widgets/Announcements.js new file mode 100644 index 000000000..4d4df8bb2 --- /dev/null +++ b/src/opnsense/www/js/widgets/Announcements.js @@ -0,0 +1,72 @@ +/* + * Copyright (C) 2024 Deciso B.V. + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, + * INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY + * AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, + * OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF + * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS + * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN + * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE + * POSSIBILITY OF SUCH DAMAGE. + */ + +import BaseTableWidget from "./BaseTableWidget.js"; + +export default class Announcements extends BaseTableWidget { + constructor() { + super(); + this.tickTimeout = 3600000; + } + + getGridOptions() { + return { + // trigger overflow-y:scroll after 650px height + sizeToContent: 650 + } + } + + getMarkup() { + let $announcements_table = this.createTable('announcements-table', { + headerPosition: 'none', + }); + + return $('
').append($announcements_table); + } + + async onWidgetTick() { + await ajaxGet('/api/core/dashboard/product_info_feed', {}, (data, status) => { + if (!data.items.length) { + $('#announcements-table').html(`${this.translations.no_feed}`); + return; + } + let rows = []; + data.items.forEach(({ title, description, link, pubDate, guid }) => { + description = $('').html(description).text(); + console.log(description); + rows.push(` +