diff options
author | Carl Schwan <carl@carlschwan.eu> | 2022-09-07 18:04:23 +0200 |
---|---|---|
committer | nextcloud-command <nextcloud-command@users.noreply.github.com> | 2022-09-15 07:46:24 +0000 |
commit | 7bd83d9dcfbf95253cbce645da82488250451472 (patch) | |
tree | f084aa5a16e43c7a6f190af5e10ee0593c35817a /apps/updatenotification | |
parent | 204a700f85e17966a15afaa2dc91250e3c8a77b4 (diff) | |
download | nextcloud-server-7bd83d9dcfbf95253cbce645da82488250451472.tar.gz nextcloud-server-7bd83d9dcfbf95253cbce645da82488250451472.zip |
Cleanup updatenotification
- Port away from jquery inside vue
- Use modern vue components when possible
- Fix some readability isssues particularly on dark theme
- Use IInitialState
- Use php7.4
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Signed-off-by: nextcloud-command <nextcloud-command@users.noreply.github.com>
Diffstat (limited to 'apps/updatenotification')
-rw-r--r-- | apps/updatenotification/lib/Settings/Admin.php | 56 | ||||
-rw-r--r-- | apps/updatenotification/src/components/UpdateNotification.vue | 177 | ||||
-rw-r--r-- | apps/updatenotification/templates/admin.php | 7 |
3 files changed, 113 insertions, 127 deletions
diff --git a/apps/updatenotification/lib/Settings/Admin.php b/apps/updatenotification/lib/Settings/Admin.php index b8062efd81f..fded4451408 100644 --- a/apps/updatenotification/lib/Settings/Admin.php +++ b/apps/updatenotification/lib/Settings/Admin.php @@ -33,6 +33,7 @@ use OC\User\Backend; use OCP\User\Backend\ICountUsersBackend; use OCA\UpdateNotification\UpdateChecker; use OCP\AppFramework\Http\TemplateResponse; +use OCP\AppFramework\Services\IInitialState; use OCP\IConfig; use OCP\IDateTimeFormatter; use OCP\IGroupManager; @@ -44,22 +45,15 @@ use OCP\IUserManager; use Psr\Log\LoggerInterface; class Admin implements ISettings { - /** @var IConfig */ - private $config; - /** @var UpdateChecker */ - private $updateChecker; - /** @var IGroupManager */ - private $groupManager; - /** @var IDateTimeFormatter */ - private $dateTimeFormatter; - /** @var IFactory */ - private $l10nFactory; - /** @var IRegistry */ - private $subscriptionRegistry; - /** @var IUserManager */ - private $userManager; - /** @var LoggerInterface */ - private $logger; + private IConfig $config; + private UpdateChecker $updateChecker; + private IGroupManager $groupManager; + private IDateTimeFormatter $dateTimeFormatter; + private IFactory $l10nFactory; + private IRegistry $subscriptionRegistry; + private IUserManager $userManager; + private LoggerInterface $logger; + private IInitialState $initialState; public function __construct( IConfig $config, @@ -69,7 +63,8 @@ class Admin implements ISettings { IFactory $l10nFactory, IRegistry $subscriptionRegistry, IUserManager $userManager, - LoggerInterface $logger + LoggerInterface $logger, + IInitialState $initialState ) { $this->config = $config; $this->updateChecker = $updateChecker; @@ -79,11 +74,9 @@ class Admin implements ISettings { $this->subscriptionRegistry = $subscriptionRegistry; $this->userManager = $userManager; $this->logger = $logger; + $this->initialState = $initialState; } - /** - * @return TemplateResponse - */ public function getForm(): TemplateResponse { $lastUpdateCheckTimestamp = $this->config->getAppValue('core', 'lastupdatedat'); $lastUpdateCheck = $this->dateTimeFormatter->formatDateTime($lastUpdateCheckTimestamp); @@ -131,12 +124,9 @@ class Admin implements ISettings { 'notifyGroups' => $this->getSelectedGroups($notifyGroups), 'hasValidSubscription' => $hasValidSubscription, ]; + $this->initialState->provideInitialState('data', $params); - $params = [ - 'json' => json_encode($params), - ]; - - return new TemplateResponse('updatenotification', 'admin', $params, ''); + return new TemplateResponse('updatenotification', 'admin', [], ''); } protected function filterChanges(array $changes): array { @@ -162,8 +152,8 @@ class Admin implements ISettings { } /** - * @param array $groupIds - * @return array + * @param list<string> $groupIds + * @return list<array{id: string, displayname: string}> */ protected function getSelectedGroups(array $groupIds): array { $result = []; @@ -174,26 +164,16 @@ class Admin implements ISettings { continue; } - $result[] = ['value' => $group->getGID(), 'label' => $group->getDisplayName()]; + $result[] = ['id' => $group->getGID(), 'displayname' => $group->getDisplayName()]; } return $result; } - /** - * @return string the section ID, e.g. 'sharing' - */ public function getSection(): string { return 'overview'; } - /** - * @return int whether the form should be rather on the top or bottom of - * the admin section. The forms are arranged in ascending order of the - * priority values. It is required to return a value between 0 and 100. - * - * E.g.: 70 - */ public function getPriority(): int { return 11; } diff --git a/apps/updatenotification/src/components/UpdateNotification.vue b/apps/updatenotification/src/components/UpdateNotification.vue index c18d65caa70..95a3927a7b7 100644 --- a/apps/updatenotification/src/components/UpdateNotification.vue +++ b/apps/updatenotification/src/components/UpdateNotification.vue @@ -1,13 +1,10 @@ <template> - <div id="updatenotification" class="followupsection"> + <NcSettingsSection id="updatenotification" :title="t('updatenotification', 'Update')"> <div class="update"> <template v-if="isNewVersionAvailable"> - <p v-if="versionIsEol"> - <span class="warning"> - <span class="icon icon-error-white" /> - {{ t('updatenotification', 'The version you are running is not maintained anymore. Please make sure to update to a supported version as soon as possible.') }} - </span> - </p> + <NcNoteCard v-if="versionIsEol" type="warning"> + {{ t('updatenotification', 'The version you are running is not maintained anymore. Please make sure to update to a supported version as soon as possible.') }} + </NcNoteCard> <p> <span v-html="newVersionAvailableString" /><br> @@ -109,24 +106,41 @@ <p id="oca_updatenotification_groups"> {{ t('updatenotification', 'Notify members of the following groups about available updates:') }} <NcMultiselect v-model="notifyGroups" - :options="availableGroups" + :options="groups" :multiple="true" - label="label" - track-by="value" - :tag-width="75" /><br> + :searchable="true" + label="displayname" + :loading="loadingGroups" + :show-no-options="false" + :close-on-select="false" + track-by="id" + :tag-width="75" + @search-change="searchGroup" /><br> <em v-if="currentChannel === 'daily' || currentChannel === 'git'">{{ t('updatenotification', 'Only notifications for app updates are available.') }}</em> <em v-if="currentChannel === 'daily'">{{ t('updatenotification', 'The selected update channel makes dedicated notifications for the server obsolete.') }}</em> <em v-if="currentChannel === 'git'">{{ t('updatenotification', 'The selected update channel does not support updates of the server.') }}</em> </p> - </div> + </NcSettingsSection> </template> <script> import { generateUrl, getRootUrl, generateOcsUrl } from '@nextcloud/router' -import NcPopoverMenu from '@nextcloud/vue/dist/Components/NcPopoverMenu' -import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect' +import NcPopoverMenu from '@nextcloud/vue/dist/Components/NcPopoverMenu.js' +import NcMultiselect from '@nextcloud/vue/dist/Components/NcMultiselect.js' +import NcSettingsSection from '@nextcloud/vue/dist/Components/NcSettingsSection.js' +import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js' import { VTooltip } from 'v-tooltip' import ClickOutside from 'vue-click-outside' +import axios from '@nextcloud/axios' +import { loadState } from '@nextcloud/initial-state' +import { showSuccess } from '@nextcloud/dialogs' +import debounce from 'debounce' +import { getLoggerBuilder } from '@nextcloud/logger' + +const logger = getLoggerBuilder() + .setApp('updatenotification') + .detectUser() + .build() VTooltip.options.defaultHtml = false @@ -135,6 +149,8 @@ export default { components: { NcMultiselect, NcPopoverMenu, + NcSettingsSection, + NcNoteCard, }, directives: { ClickOutside, @@ -142,6 +158,7 @@ export default { }, data() { return { + loadingGroups: false, newVersionString: '', lastCheckedDate: '', isUpdateChecked: false, @@ -158,7 +175,7 @@ export default { currentChannel: '', channels: [], notifyGroups: '', - availableGroups: [], + groups: [], isDefaultUpdateServerURL: true, enableChangeWatcher: false, @@ -174,9 +191,6 @@ export default { } }, - _$el: null, - _$notifyGroups: null, - computed: { newVersionAvailableString() { return t('updatenotification', 'A new version is available: <strong>{newVersionString}</strong>', { @@ -293,46 +307,41 @@ export default { watch: { notifyGroups(selectedOptions) { if (!this.enableChangeWatcher) { + // The first time is when loading the app + this.enableChangeWatcher = true return } - const selectedGroups = [] - _.each(selectedOptions, function(group) { - selectedGroups.push(group.value) + const groups = this.notifyGroups.map(group => { + return group.id }) - OCP.AppConfig.setValue('updatenotification', 'notify_groups', JSON.stringify(selectedGroups)) + OCP.AppConfig.setValue('updatenotification', 'notify_groups', JSON.stringify(groups)) }, isNewVersionAvailable() { if (!this.isNewVersionAvailable) { return } - $.ajax({ - url: generateOcsUrl('apps/updatenotification/api/v1/applist/{newVersion}', { newVersion: this.newVersion }), - type: 'GET', - beforeSend(request) { - request.setRequestHeader('Accept', 'application/json') - }, - success: function(response) { - this.availableAppUpdates = response.ocs.data.available - this.missingAppUpdates = response.ocs.data.missing - this.isListFetched = true - this.appStoreFailed = false - }.bind(this), - error: function(xhr) { - this.availableAppUpdates = [] - this.missingAppUpdates = [] - this.appStoreDisabled = xhr.responseJSON.ocs.data.appstore_disabled - this.isListFetched = true - this.appStoreFailed = true - }.bind(this), + axios.get(generateOcsUrl('apps/updatenotification/api/v1/applist/{newVersion}', { + newVersion: this.newVersion, + })).then(({ data }) => { + this.availableAppUpdates = data.ocs.data.available + this.missingAppUpdates = data.ocs.data.missing + this.isListFetched = true + this.appStoreFailed = false + }).catch(({ data }) => { + this.availableAppUpdates = [] + this.missingAppUpdates = [] + this.appStoreDisabled = data.ocs.data.appstore_disabled + this.isListFetched = true + this.appStoreFailed = true }) }, }, beforeMount() { // Parse server data - const data = JSON.parse($('#updatenotification').attr('data-json')) + const data = loadState('updatenotification', 'data') this.newVersion = data.newVersion this.newVersionString = data.newVersionString @@ -360,51 +369,50 @@ export default { this.whatsNewData = this.whatsNewData.concat(data.changes.whatsNew.regular) } }, - mounted() { - this._$el = $(this.$el) - this._$notifyGroups = this._$el.find('#oca_updatenotification_groups_list') - this._$notifyGroups.on('change', function() { - this.$emit('input') - }.bind(this)) - - $.ajax({ - url: generateOcsUrl('cloud/groups'), - dataType: 'json', - success: function(data) { - const results = [] - $.each(data.ocs.data.groups, function(i, group) { - results.push({ value: group, label: group }) - }) - this.availableGroups = results - this.enableChangeWatcher = true - }.bind(this), - }) + mounted() { + this.searchGroup() }, methods: { + searchGroup: debounce(async function(query) { + this.loadingGroups = true + try { + const response = await axios.get(generateOcsUrl('cloud/groups/details'), { + search: query, + limit: 20, + offset: 0, + }) + this.groups = response.data.ocs.data.groups.sort(function(a, b) { + return a.displayname.localeCompare(b.displayname) + }) + } catch (err) { + logger.error('Could not fetch groups', err) + } finally { + this.loadingGroups = false + } + }, 500), /** * Creates a new authentication token and loads the updater URL */ clickUpdaterButton() { - $.ajax({ - url: generateUrl('/apps/updatenotification/credentials'), - }).success(function(token) { + axios.get(generateUrl('/apps/updatenotification/credentials')) + .then(({ data }) => { // create a form to send a proper post request to the updater - const form = document.createElement('form') - form.setAttribute('method', 'post') - form.setAttribute('action', getRootUrl() + '/updater/') + const form = document.createElement('form') + form.setAttribute('method', 'post') + form.setAttribute('action', getRootUrl() + '/updater/') - const hiddenField = document.createElement('input') - hiddenField.setAttribute('type', 'hidden') - hiddenField.setAttribute('name', 'updater-secret-input') - hiddenField.setAttribute('value', token) + const hiddenField = document.createElement('input') + hiddenField.setAttribute('type', 'hidden') + hiddenField.setAttribute('name', 'updater-secret-input') + hiddenField.setAttribute('value', data.token) - form.appendChild(hiddenField) + form.appendChild(hiddenField) - document.body.appendChild(form) - form.submit() - }) + document.body.appendChild(form) + form.submit() + }) }, changeReleaseChannelToEnterprise() { this.changeReleaseChannel('enterprise') @@ -418,15 +426,10 @@ export default { changeReleaseChannel(channel) { this.currentChannel = channel - $.ajax({ - url: generateUrl('/apps/updatenotification/channel'), - type: 'POST', - data: { - channel: this.currentChannel, - }, - success(data) { - OC.msg.finishedAction('#channel_save_msg', data) - }, + axios.post(generateUrl('/apps/updatenotification/channel'), { + channel: this.currentChannel, + }).then(({ data }) => { + showSuccess(data.data.message) }) this.openedUpdateChannelMenu = false @@ -455,8 +458,10 @@ export default { <style lang="scss" scoped> #updatenotification { - margin-top: -25px; - margin-bottom: 200px; + & > * { + max-width: 900px; + } + div.update, p:not(.inlineblock) { margin-bottom: 25px; diff --git a/apps/updatenotification/templates/admin.php b/apps/updatenotification/templates/admin.php index 44bdb0375fe..a9bf18b3a4e 100644 --- a/apps/updatenotification/templates/admin.php +++ b/apps/updatenotification/templates/admin.php @@ -8,6 +8,7 @@ declare(strict_types=1); * This file is licensed under the Affero General Public License version 3 or * later. See the COPYING file. */ -script('updatenotification', 'updatenotification'); - /** @var array $_ */ ?> -<div id="updatenotification" data-json="<?php p($_['json']); ?>"></div> +\OCP\Util::addScript('updatenotification', 'updatenotification'); + ?> + +<div id="updatenotification"></div> |