summaryrefslogtreecommitdiffstats
path: root/core
diff options
context:
space:
mode:
authorMorris Jobke <hey@morrisjobke.de>2018-07-13 17:25:51 +0200
committerGitHub <noreply@github.com>2018-07-13 17:25:51 +0200
commit14314584ba88ed8d8a7c8486b61c6677a14271f2 (patch)
treea24439cf1b1c243318532322d52d89fe4530fc47 /core
parent1801e4e03f3a0b5ef253d67c13702b0fa22578a3 (diff)
parentca6094f3900fd463449d9973589b1d49aed28b2a (diff)
downloadnextcloud-server-14314584ba88ed8d8a7c8486b61c6677a14271f2.tar.gz
nextcloud-server-14314584ba88ed8d8a7c8486b61c6677a14271f2.zip
Merge pull request #10110 from nextcloud/feature/100500/whats-new-info-users
Display What's New info to users
Diffstat (limited to 'core')
-rw-r--r--core/Controller/WhatsNewController.php126
-rw-r--r--core/css/whatsnew.scss31
-rw-r--r--core/js/core.json1
-rw-r--r--core/js/merged-template-prepend.json1
-rw-r--r--core/js/public/whatsnew.js134
-rw-r--r--core/routes.php2
6 files changed, 295 insertions, 0 deletions
diff --git a/core/Controller/WhatsNewController.php b/core/Controller/WhatsNewController.php
new file mode 100644
index 00000000000..c3a6d28cea2
--- /dev/null
+++ b/core/Controller/WhatsNewController.php
@@ -0,0 +1,126 @@
+<?php
+/**
+ * @copyright Copyright (c) 2018 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Affero General Public License as
+ * published by the Free Software Foundation, either version 3 of the
+ * License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Affero General Public License for more details.
+ *
+ * You should have received a copy of the GNU Affero General Public License
+ * along with this program. If not, see <http://www.gnu.org/licenses/>.
+ *
+ */
+
+namespace OC\Core\Controller;
+
+use OC\CapabilitiesManager;
+use OC\Security\IdentityProof\Manager;
+use OC\Updater\ChangesCheck;
+use OCP\AppFramework\Db\DoesNotExistException;
+use OCP\AppFramework\Http;
+use OCP\AppFramework\Http\DataResponse;
+use OCP\Defaults;
+use OCP\IConfig;
+use OCP\IRequest;
+use OCP\IUserManager;
+use OCP\IUserSession;
+use OCP\L10N\IFactory;
+
+class WhatsNewController extends OCSController {
+
+ /** @var IConfig */
+ protected $config;
+ /** @var IUserSession */
+ private $userSession;
+ /** @var ChangesCheck */
+ private $whatsNewService;
+ /** @var IFactory */
+ private $langFactory;
+ /** @var Defaults */
+ private $defaults;
+
+ public function __construct(
+ string $appName,
+ IRequest $request,
+ CapabilitiesManager $capabilitiesManager,
+ IUserSession $userSession,
+ IUserManager $userManager,
+ Manager $keyManager,
+ IConfig $config,
+ ChangesCheck $whatsNewService,
+ IFactory $langFactory,
+ Defaults $defaults
+ ) {
+ parent::__construct($appName, $request, $capabilitiesManager, $userSession, $userManager, $keyManager);
+ $this->config = $config;
+ $this->userSession = $userSession;
+ $this->whatsNewService = $whatsNewService;
+ $this->langFactory = $langFactory;
+ $this->defaults = $defaults;
+ }
+
+ /**
+ * @NoAdminRequired
+ */
+ public function get():DataResponse {
+ $user = $this->userSession->getUser();
+ if($user === null) {
+ throw new \RuntimeException("Acting user cannot be resolved");
+ }
+ $lastRead = $this->config->getUserValue($user->getUID(), 'core', 'whatsNewLastRead', 0);
+ $currentVersion = $this->whatsNewService->normalizeVersion($this->config->getSystemValue('version'));
+
+ if(version_compare($lastRead, $currentVersion, '>=')) {
+ return new DataResponse([], Http::STATUS_NO_CONTENT);
+ }
+
+ try {
+ $iterator = $this->langFactory->getLanguageIterator();
+ $whatsNew = $this->whatsNewService->getChangesForVersion($currentVersion);
+ $resultData = [
+ 'changelogURL' => $whatsNew['changelogURL'],
+ 'product' => $this->defaults->getName(),
+ 'version' => $currentVersion,
+ ];
+ do {
+ $lang = $iterator->current();
+ if(isset($whatsNew['whatsNew'][$lang])) {
+ $resultData['whatsNew'] = $whatsNew['whatsNew'][$lang];
+ break;
+ }
+ $iterator->next();
+ } while ($lang !== 'en' && $iterator->valid());
+ return new DataResponse($resultData);
+ } catch (DoesNotExistException $e) {
+ return new DataResponse([], Http::STATUS_NO_CONTENT);
+ }
+ }
+
+ /**
+ * @NoAdminRequired
+ *
+ * @throws \OCP\PreConditionNotMetException
+ * @throws DoesNotExistException
+ */
+ public function dismiss(string $version):DataResponse {
+ $user = $this->userSession->getUser();
+ if($user === null) {
+ throw new \RuntimeException("Acting user cannot be resolved");
+ }
+ $version = $this->whatsNewService->normalizeVersion($version);
+ // checks whether it's a valid version, throws an Exception otherwise
+ $this->whatsNewService->getChangesForVersion($version);
+ $this->config->setUserValue($user->getUID(), 'core', 'whatsNewLastRead', $version);
+ return new DataResponse();
+ }
+}
diff --git a/core/css/whatsnew.scss b/core/css/whatsnew.scss
new file mode 100644
index 00000000000..1c2ab08333a
--- /dev/null
+++ b/core/css/whatsnew.scss
@@ -0,0 +1,31 @@
+/**
+ * @copyright Copyright (c) 2018, Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @license GNU AGPL version 3 or any later version
+ *
+ */
+
+.whatsNewPopover {
+ bottom: 35px !important;
+ left: 15px !important;
+ width: 270px;
+ background-color: var(--color-background-dark);
+}
+
+.whatsNewPopover p {
+ width: auto !important;
+}
+
+.whatsNewPopover .caption {
+ font-weight: bolder;
+ cursor: auto !important;
+}
+
+.whatsNewPopover .icon-close {
+ position: absolute;
+ right: 0;
+}
+
+.whatsNewPopover::after {
+ content: none;
+}
diff --git a/core/js/core.json b/core/js/core.json
index 41b927147b6..502e3a57976 100644
--- a/core/js/core.json
+++ b/core/js/core.json
@@ -48,6 +48,7 @@
"public/appconfig.js",
"public/comments.js",
"public/publicpage.js",
+ "public/whatsnew.js",
"multiselect.js",
"oc-requesttoken.js",
"setupchecks.js",
diff --git a/core/js/merged-template-prepend.json b/core/js/merged-template-prepend.json
index f4ef511bc78..c274201d97e 100644
--- a/core/js/merged-template-prepend.json
+++ b/core/js/merged-template-prepend.json
@@ -7,6 +7,7 @@
"eventsource.js",
"public/appconfig.js",
"public/comments.js",
+ "public/whatsnew.js",
"config.js",
"oc-requesttoken.js",
"apps.js",
diff --git a/core/js/public/whatsnew.js b/core/js/public/whatsnew.js
new file mode 100644
index 00000000000..20a871ada27
--- /dev/null
+++ b/core/js/public/whatsnew.js
@@ -0,0 +1,134 @@
+/**
+ * @copyright (c) 2017 Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * @author Arthur Schiwon <blizzz@arthur-schiwon.de>
+ *
+ * This file is licensed under the Affero General Public License version 3 or
+ * later. See the COPYING file.
+ */
+
+(function(OCP) {
+ "use strict";
+
+ OCP.WhatsNew = {
+
+ query: function(options) {
+ options = options || {};
+ var dismissOptions = options.dismiss || {};
+ $.ajax({
+ type: 'GET',
+ url: options.url || OC.linkToOCS('core', 2) + 'whatsnew?format=json',
+ success: options.success || function(data, statusText, xhr) {
+ OCP.WhatsNew._onQuerySuccess(data, statusText, xhr, dismissOptions);
+ },
+ error: options.error || this._onQueryError
+ });
+ },
+
+ dismiss: function(version, options) {
+ options = options || {};
+ $.ajax({
+ type: 'POST',
+ url: options.url || OC.linkToOCS('core', 2) + 'whatsnew',
+ data: {version: encodeURIComponent(version)},
+ success: options.success || this._onDismissSuccess,
+ error: options.error || this._onDismissError
+ });
+ // remove element immediately
+ $('.whatsNewPopover').remove();
+ },
+
+ _onQuerySuccess: function(data, statusText, xhr, dismissOptions) {
+ console.debug('querying Whats New data was successful: ' + statusText);
+ console.debug(data);
+
+ if(xhr.status !== 200) {
+ return;
+ }
+
+ var item, menuItem, text, icon;
+
+ var div = document.createElement('div');
+ div.classList.add('popovermenu', 'open', 'whatsNewPopover', 'menu-left');
+
+ var list = document.createElement('ul');
+
+ // header
+ item = document.createElement('li');
+ menuItem = document.createElement('span');
+ menuItem.className = "menuitem";
+
+ text = document.createElement('span');
+ text.innerText = t('core', 'New in') + ' ' + data['ocs']['data']['product'];
+ text.className = 'caption';
+ menuItem.appendChild(text);
+
+ icon = document.createElement('span');
+ icon.className = 'icon-close';
+ icon.onclick = function () {
+ OCP.WhatsNew.dismiss(data['ocs']['data']['version'], dismissOptions);
+ };
+ menuItem.appendChild(icon);
+
+ item.appendChild(menuItem);
+ list.appendChild(item);
+
+ // Highlights
+ for (var i in data['ocs']['data']['whatsNew']['regular']) {
+ var whatsNewTextItem = data['ocs']['data']['whatsNew']['regular'][i];
+ item = document.createElement('li');
+
+ menuItem = document.createElement('span');
+ menuItem.className = "menuitem";
+
+ icon = document.createElement('span');
+ icon.className = 'icon-star-dark';
+ menuItem.appendChild(icon);
+
+ text = document.createElement('p');
+ text.innerHTML = _.escape(whatsNewTextItem);
+ menuItem.appendChild(text);
+
+ item.appendChild(menuItem);
+ list.appendChild(item);
+ }
+
+ // Changelog URL
+ if(!_.isUndefined(data['ocs']['data']['changelogURL'])) {
+ item = document.createElement('li');
+
+ menuItem = document.createElement('a');
+ menuItem.href = data['ocs']['data']['changelogURL'];
+ menuItem.rel = 'noreferrer noopener';
+ menuItem.target = '_blank';
+
+ icon = document.createElement('span');
+ icon.className = 'icon-link';
+ menuItem.appendChild(icon);
+
+ text = document.createElement('span');
+ text.innerText = t('core', 'View changelog');
+ menuItem.appendChild(text);
+
+ item.appendChild(menuItem);
+ list.appendChild(item);
+ }
+
+ div.appendChild(list);
+ document.body.appendChild(div);
+ },
+
+ _onQueryError: function (x, t, e) {
+ console.debug('querying Whats New Data resulted in an error: ' + t + e);
+ console.debug(x);
+ },
+
+ _onDismissSuccess: function(data) {
+ //noop
+ },
+
+ _onDismissError: function (data) {
+ console.debug('dismissing Whats New data resulted in an error: ' + data);
+ }
+ };
+})(OCP);
diff --git a/core/routes.php b/core/routes.php
index 90282c5ebf7..c5df3a362f5 100644
--- a/core/routes.php
+++ b/core/routes.php
@@ -76,6 +76,8 @@ $application->registerRoutes($this, [
['root' => '/core', 'name' => 'Navigation#getAppsNavigation', 'url' => '/navigation/apps', 'verb' => 'GET'],
['root' => '/core', 'name' => 'Navigation#getSettingsNavigation', 'url' => '/navigation/settings', 'verb' => 'GET'],
['root' => '/core', 'name' => 'AutoComplete#get', 'url' => '/autocomplete/get', 'verb' => 'GET'],
+ ['root' => '/core', 'name' => 'WhatsNew#get', 'url' => '/whatsnew', 'verb' => 'GET'],
+ ['root' => '/core', 'name' => 'WhatsNew#dismiss', 'url' => '/whatsnew', 'verb' => 'POST'],
],
]);