diff options
author | Carl Schwan <carl@carlschwan.eu> | 2022-02-10 23:56:05 +0100 |
---|---|---|
committer | Carl Schwan <carl@carlschwan.eu> | 2022-02-17 17:52:03 +0100 |
commit | 7c8a901b841878c7d63940baa551f5982958874e (patch) | |
tree | faf0c431d93cad5f294c4b09e14d3c1645f1bb5f /apps/settings | |
parent | f5d1365bbd32fdcf2084eb2ad727a574529898d0 (diff) | |
download | nextcloud-server-7c8a901b841878c7d63940baa551f5982958874e.tar.gz nextcloud-server-7c8a901b841878c7d63940baa551f5982958874e.zip |
Cleanup admin settings js files
* Move admin.js to webpack, so that this use the bundled jquery files
instead of the deprecated window.$ Also fixing formatting
* Remove log.js that seems to be from a time where logreader was bundled
with server and I couldn't find an usage of it anymore
* Fix recent regression in rebuild navigation function (now not depending on
jquery anymore and bundled by webpack).
Signed-off-by: Carl Schwan <carl@carlschwan.eu>
Diffstat (limited to 'apps/settings')
-rw-r--r-- | apps/settings/css/settings.scss | 15 | ||||
-rw-r--r-- | apps/settings/js/admin.js | 333 | ||||
-rw-r--r-- | apps/settings/js/apps.js | 113 | ||||
-rw-r--r-- | apps/settings/js/log.js | 85 | ||||
-rw-r--r-- | apps/settings/lib/Controller/AppSettingsController.php | 1 | ||||
-rw-r--r-- | apps/settings/src/admin.js | 335 | ||||
-rw-r--r-- | apps/settings/src/mixins/AppManagement.js | 27 | ||||
-rw-r--r-- | apps/settings/src/service/rebuild-navigation.js | 130 | ||||
-rw-r--r-- | apps/settings/src/store/apps.js | 16 | ||||
-rw-r--r-- | apps/settings/templates/settings/frame.php | 3 |
10 files changed, 506 insertions, 552 deletions
diff --git a/apps/settings/css/settings.scss b/apps/settings/css/settings.scss index 7b261d67181..d9073b9a138 100644 --- a/apps/settings/css/settings.scss +++ b/apps/settings/css/settings.scss @@ -1755,3 +1755,18 @@ doesnotexist:-o-prefocus, .strengthify-wrapper { } } } + +.animated { + animation: blink-animation 1s steps(5, start) 4; +} + +@keyframes blink-animation { + to { + opacity: 0.6; + } +} +@-webkit-keyframes blink-animation { + to { + opacity: 1; + } +} diff --git a/apps/settings/js/admin.js b/apps/settings/js/admin.js deleted file mode 100644 index 20d9843fe14..00000000000 --- a/apps/settings/js/admin.js +++ /dev/null @@ -1,333 +0,0 @@ -window.addEventListener('DOMContentLoaded', function(){ - $('#excludedGroups,#linksExcludedGroups').each(function (index, element) { - OC.Settings.setupGroupsSelect($(element)); - $(element).change(function(ev) { - var groups = ev.val || []; - groups = JSON.stringify(groups); - OCP.AppConfig.setValue('core', $(this).attr('name'), groups); - }); - }); - - - $('#loglevel').change(function(){ - $.post(OC.generateUrl('/settings/admin/log/level'), {level: $(this).val()},function(){ - OC.Log.reload(); - } ); - }); - - $('#backgroundjobs span.crondate').tooltip({placement: 'top'}); - - $('#backgroundjobs input').change(function(){ - if($(this).is(':checked')){ - var mode = $(this).val(); - if (mode === 'ajax' || mode === 'webcron' || mode === 'cron') { - OCP.AppConfig.setValue('core', 'backgroundjobs_mode', mode, { - success: function() { - // clear cron errors on background job mode change - OCP.AppConfig.deleteKey('core', 'cronErrors'); - } - }); - } - } - }); - - $('#shareAPIEnabled').change(function() { - $('#shareAPI p:not(#enable)').toggleClass('hidden', !this.checked); - }); - - $('#enableEncryption').change(function() { - $('#encryptionAPI div#EncryptionWarning').toggleClass('hidden'); - }); - - $('#reallyEnableEncryption').click(function() { - $('#encryptionAPI div#EncryptionWarning').toggleClass('hidden'); - $('#encryptionAPI div#EncryptionSettingsArea').toggleClass('hidden'); - OCP.AppConfig.setValue('core', 'encryption_enabled', 'yes'); - $('#enableEncryption').attr('disabled', 'disabled'); - }); - - $('#startmigration').click(function(event){ - $(window).on('beforeunload.encryption', function(e) { - return t('settings', 'Migration in progress. Please wait until the migration is finished'); - }); - event.preventDefault(); - $('#startmigration').prop('disabled', true); - OC.msg.startAction('#startmigration_msg', t('settings', 'Migration started …')); - $.post(OC.generateUrl('/settings/admin/startmigration'), '', function(data){ - OC.msg.finishedAction('#startmigration_msg', data); - if (data['status'] === 'success') { - $('#encryptionAPI div#selectEncryptionModules').toggleClass('hidden'); - $('#encryptionAPI div#migrationWarning').toggleClass('hidden'); - } else { - $('#startmigration').prop('disabled', false); - } - $(window).off('beforeunload.encryption'); - - }); - }); - - $('#shareapiExpireAfterNDays').on('input', function() { - this.value = this.value.replace(/\D/g, ''); - }); - - $('#shareAPI input:not(.noJSAutoUpdate)').change(function() { - var value = $(this).val(); - if ($(this).attr('type') === 'checkbox') { - if (this.checked) { - value = 'yes'; - } else { - value = 'no'; - } - } - OCP.AppConfig.setValue('core', $(this).attr('name'), value); - }); - - $('#shareapiDefaultExpireDate').change(function() { - $("#setDefaultExpireDate").toggleClass('hidden', !this.checked); - }); - - $('#shareapiDefaultInternalExpireDate').change(function() { - $("#setDefaultInternalExpireDate").toggleClass('hidden', !this.checked); - }); - - $('#shareapiDefaultRemoteExpireDate').change(function() { - $("#setDefaultRemoteExpireDate").toggleClass('hidden', !this.checked); - }); - - $('#publicShareDisclaimer').change(function() { - $("#publicShareDisclaimerText").toggleClass('hidden', !this.checked); - if(!this.checked) { - savePublicShareDisclaimerText(''); - } - }); - - $('#shareApiDefaultPermissionsSection input').change(function(ev) { - var $el = $('#shareApiDefaultPermissions'); - var $target = $(ev.target); - - var value = $el.val(); - if ($target.is(':checked')) { - value = value | $target.val(); - } else { - value = value & ~$target.val(); - } - - // always set read permission - value |= OC.PERMISSION_READ; - - // this will trigger the field's change event and will save it - $el.val(value).change(); - - ev.preventDefault(); - - return false; - }); - - var savePublicShareDisclaimerText = _.debounce(function(value) { - var options = { - success: function() { - OC.msg.finishedSuccess('#publicShareDisclaimerStatus', t('settings', 'Saved')); - }, - error: function() { - OC.msg.finishedError('#publicShareDisclaimerStatus', t('settings', 'Not saved')); - } - }; - - OC.msg.startSaving('#publicShareDisclaimerStatus'); - if (_.isString(value) && value !== '') { - OCP.AppConfig.setValue('core', 'shareapi_public_link_disclaimertext', value, options); - } else { - $('#publicShareDisclaimerText').val(''); - OCP.AppConfig.deleteKey('core', 'shareapi_public_link_disclaimertext', options); - } - }, 500); - - $('#publicShareDisclaimerText').on('change, keyup', function() { - savePublicShareDisclaimerText(this.value); - }); - - $('#shareapi_allow_share_dialog_user_enumeration').on('change', function() { - $('#shareapi_restrict_user_enumeration_to_group_setting').toggleClass('hidden', !this.checked); - $('#shareapi_restrict_user_enumeration_to_phone_setting').toggleClass('hidden', !this.checked); - $('#shareapi_restrict_user_enumeration_combinewarning_setting').toggleClass('hidden', !this.checked); - }) - - $('#allowLinks').change(function() { - $("#publicLinkSettings").toggleClass('hidden', !this.checked); - $('#setDefaultExpireDate').toggleClass('hidden', !(this.checked && $('#shareapiDefaultExpireDate')[0].checked)); - }); - - $('#mail_smtpauth').change(function() { - if (!this.checked) { - $('#mail_credentials').addClass('hidden'); - } else { - $('#mail_credentials').removeClass('hidden'); - } - }); - - $('#mail_smtpmode').change(function() { - if ($(this).val() !== 'smtp') { - $('#setting_smtpauth').addClass('hidden'); - $('#setting_smtphost').addClass('hidden'); - $('#mail_smtpsecure_label').addClass('hidden'); - $('#mail_smtpsecure').addClass('hidden'); - $('#mail_credentials').addClass('hidden'); - $('#mail_sendmailmode_label, #mail_sendmailmode').removeClass('hidden'); - } else { - $('#setting_smtpauth').removeClass('hidden'); - $('#setting_smtphost').removeClass('hidden'); - $('#mail_smtpsecure_label').removeClass('hidden'); - $('#mail_smtpsecure').removeClass('hidden'); - if ($('#mail_smtpauth').is(':checked')) { - $('#mail_credentials').removeClass('hidden'); - } - $('#mail_sendmailmode_label, #mail_sendmailmode').addClass('hidden'); - } - }); - - var changeEmailSettings = function() { - if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { - OC.PasswordConfirmation.requirePasswordConfirmation(changeEmailSettings); - return; - } - - OC.msg.startSaving('#mail_settings_msg'); - $.ajax({ - url: OC.generateUrl('/settings/admin/mailsettings'), - type: 'POST', - data: $('#mail_general_settings_form').serialize(), - success: function(){ - OC.msg.finishedSuccess('#mail_settings_msg', t('settings', 'Saved')); - }, - error: function(xhr){ - OC.msg.finishedError('#mail_settings_msg', xhr.responseJSON); - } - }); - }; - - var toggleEmailCredentials = function() { - if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { - OC.PasswordConfirmation.requirePasswordConfirmation(toggleEmailCredentials); - return; - } - - OC.msg.startSaving('#mail_settings_msg'); - $.ajax({ - url: OC.generateUrl('/settings/admin/mailsettings/credentials'), - type: 'POST', - data: $('#mail_credentials_settings').serialize(), - success: function(){ - OC.msg.finishedSuccess('#mail_settings_msg', t('settings', 'Saved')); - }, - error: function(xhr){ - OC.msg.finishedError('#mail_settings_msg', xhr.responseJSON); - } - }); - }; - - $('#mail_general_settings_form').change(changeEmailSettings); - $('#mail_credentials_settings_submit').click(toggleEmailCredentials); - $('#mail_smtppassword').click(function() { - if (this.type === 'text' && this.value === '********') { - this.type = 'password'; - this.value = ''; - } - }); - - $('#sendtestemail').click(function(event){ - event.preventDefault(); - OC.msg.startAction('#sendtestmail_msg', t('settings', 'Sending…')); - - $.ajax({ - url: OC.generateUrl('/settings/admin/mailtest'), - type: 'POST', - success: function(){ - OC.msg.finishedSuccess('#sendtestmail_msg', t('settings', 'Email sent')); - }, - error: function(xhr){ - OC.msg.finishedError('#sendtestmail_msg', xhr.responseJSON); - } - }); - }); - - $('#allowGroupSharing').change(function() { - $('#allowGroupSharing').toggleClass('hidden', !this.checked); - }); - - $('#shareapiExcludeGroups').change(function() { - $("#selectExcludedGroups").toggleClass('hidden', !this.checked); - }); - - var setupChecks = function () { - // run setup checks then gather error messages - $.when( - OC.SetupChecks.checkWebDAV(), - OC.SetupChecks.checkWellKnownUrl('GET', '/.well-known/webfinger', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true, [200, 404], true), - OC.SetupChecks.checkWellKnownUrl('GET', '/.well-known/nodeinfo', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true, [200, 404], true), - OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/caldav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), - OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/carddav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), - OC.SetupChecks.checkProviderUrl(OC.getRootPath() + '/ocm-provider/', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), - OC.SetupChecks.checkProviderUrl(OC.getRootPath() + '/ocs-provider/', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), - OC.SetupChecks.checkSetup(), - OC.SetupChecks.checkGeneric(), - OC.SetupChecks.checkWOFF2Loading(OC.filePath('core', '', 'fonts/NotoSans-Regular-latin.woff2'), OC.theme.docPlaceholderUrl), - OC.SetupChecks.checkDataProtected() - ).then(function (check1, check2, check3, check4, check5, check6, check7, check8, check9, check10, check11) { - var messages = [].concat(check1, check2, check3, check4, check5, check6, check7, check8, check9, check10, check11); - var $el = $('#postsetupchecks'); - $('#security-warning-state-loading').addClass('hidden'); - - var hasMessages = false; - var $errorsEl = $el.find('.errors'); - var $warningsEl = $el.find('.warnings'); - var $infoEl = $el.find('.info'); - - for (var i = 0; i < messages.length; i++) { - switch (messages[i].type) { - case OC.SetupChecks.MESSAGE_TYPE_INFO: - $infoEl.append('<li>' + messages[i].msg + '</li>'); - break; - case OC.SetupChecks.MESSAGE_TYPE_WARNING: - $warningsEl.append('<li>' + messages[i].msg + '</li>'); - break; - case OC.SetupChecks.MESSAGE_TYPE_ERROR: - default: - $errorsEl.append('<li>' + messages[i].msg + '</li>'); - } - } - - if ($errorsEl.find('li').length > 0) { - $errorsEl.removeClass('hidden'); - hasMessages = true; - } - if ($warningsEl.find('li').length > 0) { - $warningsEl.removeClass('hidden'); - hasMessages = true; - } - if ($infoEl.find('li').length > 0) { - $infoEl.removeClass('hidden'); - hasMessages = true; - } - - if (hasMessages) { - $('#postsetupchecks-hint').removeClass('hidden'); - if ($errorsEl.find('li').length > 0) { - $('#security-warning-state-failure').removeClass('hidden'); - } else { - $('#security-warning-state-warning').removeClass('hidden'); - } - } else { - var securityWarning = $('#security-warning'); - if (securityWarning.children('ul').children().length === 0) { - $('#security-warning-state-ok').removeClass('hidden'); - } else { - $('#security-warning-state-failure').removeClass('hidden'); - } - } - }); - }; - - if (document.getElementById('security-warning') !== null) { - setupChecks(); - } -}); diff --git a/apps/settings/js/apps.js b/apps/settings/js/apps.js deleted file mode 100644 index a3c1650e445..00000000000 --- a/apps/settings/js/apps.js +++ /dev/null @@ -1,113 +0,0 @@ -/* global Handlebars */ -OC.Settings = OC.Settings || {}; -OC.Settings.Apps = OC.Settings.Apps || { - rebuildNavigation: function() { - $.getJSON(OC.linkToOCS('core/navigation', 2) + 'apps?format=json').done(function(response){ - if(response.ocs.meta.status === 'ok') { - var addedApps = {}; - var navEntries = response.ocs.data; - var container = $('#navigation #apps ul'); - - // remove disabled apps - for (var i = 0; i < navEntries.length; i++) { - var entry = navEntries[i]; - if(container.children('li[data-id="' + entry.id + '"]').length === 0) { - addedApps[entry.id] = true; - } - } - container.children('li[data-id]').each(function (index, el) { - var id = $(el).data('id'); - // remove all apps that are not in the correct order - if (!navEntries[index] || (navEntries[index] && navEntries[index].id !== $(el).data('id'))) { - $(el).remove(); - $('#appmenu li[data-id='+id+']').remove(); - } - }); - - var previousEntry = {}; - // add enabled apps to #navigation and #appmenu - for (var i = 0; i < navEntries.length; i++) { - var entry = navEntries[i]; - if (container.children('li[data-id="' + entry.id + '"]').length === 0) { - var li = $('<li></li>'); - li.attr('data-id', entry.id); - var img = '<svg width="20" height="20" viewBox="0 0 20 20" alt="">'; - if (OCA.Theming && OCA.Theming.inverted) { - img += '<defs><filter id="invert"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" /></filter></defs>'; - img += '<image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="' + entry.icon + '" class="app-icon" />'; - } else { - img += '<image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" xlink:href="' + entry.icon + '" class="app-icon" />'; - } - img += '</svg>'; - var a = $('<a></a>').attr('href', entry.href); - var filename = $('<span></span>'); - var loading = $('<div class="icon-loading-dark"></div>').css('display', 'none'); - filename.text(entry.name); - a.prepend(loading); - a.prepend(filename); - a.prepend(img); - li.append(a); - - // add app icon to the navigation - var previousElement = $('#navigation li[data-id=' + previousEntry.id + ']'); - if (previousElement.length > 0) { - previousElement.after(li); - } else { - $('#navigation #apps').prepend(li); - } - - // draw attention to the newly added app entry - // by flashing twice the more apps menu - if(addedApps[entry.id]) { - $('#header #more-apps') - .animate({opacity: 0.5}) - .animate({opacity: 1}) - .animate({opacity: 0.5}) - .animate({opacity: 1}); - } - } - - if ($('#appmenu').children('li[data-id="' + entry.id + '"]').length === 0) { - var li = $('<li></li>'); - li.attr('data-id', entry.id); - // Generating svg embedded image (see layout.user.php) - var img = '<svg width="20" height="20" viewBox="0 0 20 20" alt="">'; - if (OCA.Theming && OCA.Theming.inverted) { - img += '<defs><filter id="invert"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" /></filter></defs>'; - img += '<image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="' + entry.icon + '" class="app-icon" />'; - } else { - img += '<image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" xlink:href="' + entry.icon + '" class="app-icon" />'; - } - img += '</svg>'; - var a = $('<a></a>').attr('href', entry.href); - var filename = $('<span></span>'); - var loading = $('<div class="icon-loading-dark"></div>').css('display', 'none'); - filename.text(entry.name); - a.prepend(loading); - a.prepend(filename); - a.prepend(img); - li.append(a); - - // add app icon to the navigation - var previousElement = $('#appmenu li[data-id=' + previousEntry.id + ']'); - if (previousElement.length > 0) { - previousElement.after(li); - } else { - $('#appmenu').prepend(li); - } - - if(addedApps[entry.id]) { - li.animate({opacity: 0.5}) - .animate({opacity: 1}) - .animate({opacity: 0.5}) - .animate({opacity: 1}); - } - } - previousEntry = entry; - } - - $(window).trigger('resize'); - } - }); - } -}; diff --git a/apps/settings/js/log.js b/apps/settings/js/log.js deleted file mode 100644 index 45cc9321c24..00000000000 --- a/apps/settings/js/log.js +++ /dev/null @@ -1,85 +0,0 @@ -/** - * Copyright (c) 2012, Robin Appelman <icewind1991@gmail.com> - * Copyright (c) 2013, Morris Jobke <morris.jobke@gmail.com> - * This file is licensed under the Affero General Public License version 3 or later. - * See the COPYING-README file. - */ - -/* global formatDate */ - -OC.Log = { - reload: function (count) { - if (!count) { - count = OC.Log.loaded; - } - OC.Log.loaded = 0; - $('#log tbody').empty(); - OC.Log.getMore(count); - }, - levels: ['Debug', 'Info', 'Warning', 'Error', 'Fatal'], - loaded: 3,//are initially loaded - getMore: function (count) { - count = count || 10; - $.get(OC.generateUrl('/settings/admin/log/entries'), {offset: OC.Log.loaded, count: count}, function (result) { - OC.Log.addEntries(result.data); - if (!result.remain) { - $('#moreLog').hide(); - } - $('#lessLog').show(); - }); - }, - showLess: function (count) { - count = count || 10; - //calculate remaining items - at least 3 - OC.Log.loaded = Math.max(3, OC.Log.loaded - count); - $('#moreLog').show(); - // remove all non-remaining items - $('#log tr').slice(OC.Log.loaded).remove(); - if (OC.Log.loaded <= 3) { - $('#lessLog').hide(); - } - }, - addEntries: function (entries) { - for (var i = 0; i < entries.length; i++) { - var entry = entries[i]; - var row = $('<tr/>'); - var levelTd = $('<td/>'); - levelTd.text(OC.Log.levels[entry.level]); - row.append(levelTd); - - var appTd = $('<td/>'); - appTd.text(entry.app); - row.append(appTd); - - var messageTd = $('<td/>'); - messageTd.addClass('log-message'); - messageTd.text(entry.message); - row.append(messageTd); - - var timeTd = $('<td/>'); - timeTd.addClass('date'); - if (isNaN(entry.time)) { - timeTd.text(entry.time); - } else { - timeTd.text(formatDate(entry.time * 1000)); - } - row.append(timeTd); - - var userTd = $('<td/>'); - userTd.text(entry.user); - row.append(userTd); - - $('#log').append(row); - } - OC.Log.loaded += entries.length; - } -}; - -window.addEventListener('DOMContentLoaded', function () { - $('#moreLog').click(function () { - OC.Log.getMore(); - }); - $('#lessLog').click(function () { - OC.Log.showLess(); - }); -}); diff --git a/apps/settings/lib/Controller/AppSettingsController.php b/apps/settings/lib/Controller/AppSettingsController.php index 8dbe9fb2f07..77f807943cd 100644 --- a/apps/settings/lib/Controller/AppSettingsController.php +++ b/apps/settings/lib/Controller/AppSettingsController.php @@ -129,7 +129,6 @@ class AppSettingsController extends Controller { * @return TemplateResponse */ public function viewApps(): TemplateResponse { - \OC_Util::addScript('settings', 'apps'); $params = []; $params['appstoreEnabled'] = $this->config->getSystemValueBool('appstoreenabled', true); $params['updateCount'] = count($this->getAppsWithUpdates()); diff --git a/apps/settings/src/admin.js b/apps/settings/src/admin.js new file mode 100644 index 00000000000..24f95ccb2a6 --- /dev/null +++ b/apps/settings/src/admin.js @@ -0,0 +1,335 @@ +import $ from 'jquery' +import 'jquery-ui-dist/jquery-ui' + +window.addEventListener('DOMContentLoaded', () => { + $('#excludedGroups,#linksExcludedGroups').each((index, element) => { + OC.Settings.setupGroupsSelect($(element)) + $(element).change((ev) => { + let groups = ev.val || [] + groups = JSON.stringify(groups) + OCP.AppConfig.setValue('core', $(this).attr('name'), groups) + }) + }) + + $('#loglevel').change(() => { + $.post(OC.generateUrl('/settings/admin/log/level'), { level: $(this).val() }, () => { + OC.Log.reload() + }) + }) + + $('#backgroundjobs span.crondate').tooltip({ placement: 'top' }) + + $('#backgroundjobs input').change(() => { + if ($(this).is(':checked')) { + const mode = $(this).val() + if (mode === 'ajax' || mode === 'webcron' || mode === 'cron') { + OCP.AppConfig.setValue('core', 'backgroundjobs_mode', mode, { + success: () => { + // clear cron errors on background job mode change + OCP.AppConfig.deleteKey('core', 'cronErrors') + } + }) + } + } + }) + + $('#shareAPIEnabled').change(() => { + $('#shareAPI p:not(#enable)').toggleClass('hidden', !this.checked) + }) + + $('#enableEncryption').change(() => { + $('#encryptionAPI div#EncryptionWarning').toggleClass('hidden') + }) + + $('#reallyEnableEncryption').click(() => { + $('#encryptionAPI div#EncryptionWarning').toggleClass('hidden') + $('#encryptionAPI div#EncryptionSettingsArea').toggleClass('hidden') + OCP.AppConfig.setValue('core', 'encryption_enabled', 'yes') + $('#enableEncryption').attr('disabled', 'disabled') + }) + + $('#startmigration').click((event) => { + $(window).on('beforeunload.encryption', (e) => { + return t('settings', 'Migration in progress. Please wait until the migration is finished') + }) + event.preventDefault() + $('#startmigration').prop('disabled', true) + OC.msg.startAction('#startmigration_msg', t('settings', 'Migration started …')) + $.post(OC.generateUrl('/settings/admin/startmigration'), '', function(data) { + OC.msg.finishedAction('#startmigration_msg', data) + if (data.status === 'success') { + $('#encryptionAPI div#selectEncryptionModules').toggleClass('hidden') + $('#encryptionAPI div#migrationWarning').toggleClass('hidden') + } else { + $('#startmigration').prop('disabled', false) + } + $(window).off('beforeunload.encryption') + + }) + }) + + $('#shareapiExpireAfterNDays').on('input', function() { + this.value = this.value.replace(/\D/g, '') + }) + + $('#shareAPI input:not(.noJSAutoUpdate)').change(function() { + let value = $(this).val() + if ($(this).attr('type') === 'checkbox') { + if (this.checked) { + value = 'yes' + } else { + value = 'no' + } + } + OCP.AppConfig.setValue('core', $(this).attr('name'), value) + }) + + $('#shareapiDefaultExpireDate').change(function() { + $('setDefaultExpireDate').toggleClass('hidden', !this.checked) + }) + + $('#shareapiDefaultInternalExpireDate').change(function() { + $('#setDefaultInternalExpireDate').toggleClass('hidden', !this.checked) + }) + + $('#shareapiDefaultRemoteExpireDate').change(function() { + $('#setDefaultRemoteExpireDate').toggleClass('hidden', !this.checked) + }) + + $('#publicShareDisclaimer').change(function() { + $('#publicShareDisclaimerText').toggleClass('hidden', !this.checked) + if (!this.checked) { + savePublicShareDisclaimerText('') + } + }) + + $('#shareApiDefaultPermissionsSection input').change(function(ev) { + const $el = $('#shareApiDefaultPermissions') + const $target = $(ev.target) + + let value = $el.val() + if ($target.is(':checked')) { + value = value | $target.val() + } else { + value = value & ~$target.val() + } + + // always set read permission + value |= OC.PERMISSION_READ + + // this will trigger the field's change event and will save it + $el.val(value).change() + + ev.preventDefault() + + return false + }) + + const savePublicShareDisclaimerText = _.debounce(function(value) { + const options = { + success: () => { + OC.msg.finishedSuccess('#publicShareDisclaimerStatus', t('settings', 'Saved')) + }, + error: () => { + OC.msg.finishedError('#publicShareDisclaimerStatus', t('settings', 'Not saved')) + } + } + + OC.msg.startSaving('#publicShareDisclaimerStatus') + if (_.isString(value) && value !== '') { + OCP.AppConfig.setValue('core', 'shareapi_public_link_disclaimertext', value, options) + } else { + $('#publicShareDisclaimerText').val('') + OCP.AppConfig.deleteKey('core', 'shareapi_public_link_disclaimertext', options) + } + }, 500) + + $('#publicShareDisclaimerText').on('change, keyup', function() { + savePublicShareDisclaimerText(this.value) + }) + + $('#shareapi_allow_share_dialog_user_enumeration').on('change', function() { + $('#shareapi_restrict_user_enumeration_to_group_setting').toggleClass('hidden', !this.checked) + $('#shareapi_restrict_user_enumeration_to_phone_setting').toggleClass('hidden', !this.checked) + $('#shareapi_restrict_user_enumeration_combinewarning_setting').toggleClass('hidden', !this.checked) + }) + + $('#allowLinks').change(function() { + $('#publicLinkSettings').toggleClass('hidden', !this.checked) + $('#setDefaultExpireDate').toggleClass('hidden', !(this.checked && $('#shareapiDefaultExpireDate')[0].checked)) + }) + + $('#mail_smtpauth').change(function() { + if (!this.checked) { + $('#mail_credentials').addClass('hidden') + } else { + $('#mail_credentials').removeClass('hidden') + } + }) + + $('#mail_smtpmode').change(function() { + if ($(this).val() !== 'smtp') { + $('#setting_smtpauth').addClass('hidden') + $('#setting_smtphost').addClass('hidden') + $('#mail_smtpsecure_label').addClass('hidden') + $('#mail_smtpsecure').addClass('hidden') + $('#mail_credentials').addClass('hidden') + $('#mail_sendmailmode_label, #mail_sendmailmode').removeClass('hidden') + } else { + $('#setting_smtpauth').removeClass('hidden') + $('#setting_smtphost').removeClass('hidden') + $('#mail_smtpsecure_label').removeClass('hidden') + $('#mail_smtpsecure').removeClass('hidden') + if ($('#mail_smtpauth').is(':checked')) { + $('#mail_credentials').removeClass('hidden') + } + $('#mail_sendmailmode_label, #mail_sendmailmode').addClass('hidden') + } + }) + + const changeEmailSettings = function() { + if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { + OC.PasswordConfirmation.requirePasswordConfirmation(changeEmailSettings) + return + } + + OC.msg.startSaving('#mail_settings_msg') + $.ajax({ + url: OC.generateUrl('/settings/admin/mailsettings'), + type: 'POST', + data: $('#mail_general_settings_form').serialize(), + success: () => { + OC.msg.finishedSuccess('#mail_settings_msg', t('settings', 'Saved')) + }, + error: (xhr) => { + OC.msg.finishedError('#mail_settings_msg', xhr.responseJSON) + } + }) + } + + const toggleEmailCredentials = function() { + if (OC.PasswordConfirmation.requiresPasswordConfirmation()) { + OC.PasswordConfirmation.requirePasswordConfirmation(toggleEmailCredentials) + return + } + + OC.msg.startSaving('#mail_settings_msg') + $.ajax({ + url: OC.generateUrl('/settings/admin/mailsettings/credentials'), + type: 'POST', + data: $('#mail_credentials_settings').serialize(), + success: () => { + OC.msg.finishedSuccess('#mail_settings_msg', t('settings', 'Saved')) + }, + error: (xhr) => { + OC.msg.finishedError('#mail_settings_msg', xhr.responseJSON) + } + }) + } + + $('#mail_general_settings_form').change(changeEmailSettings) + $('#mail_credentials_settings_submit').click(toggleEmailCredentials) + $('#mail_smtppassword').click(() => { + if (this.type === 'text' && this.value === '********') { + this.type = 'password' + this.value = '' + } + }) + + $('#sendtestemail').click((event) => { + event.preventDefault() + OC.msg.startAction('#sendtestmail_msg', t('settings', 'Sending…')) + + $.ajax({ + url: OC.generateUrl('/settings/admin/mailtest'), + type: 'POST', + success: () => { + OC.msg.finishedSuccess('#sendtestmail_msg', t('settings', 'Email sent')) + }, + error: (xhr) => { + OC.msg.finishedError('#sendtestmail_msg', xhr.responseJSON) + } + }) + }) + + $('#allowGroupSharing').change(() => { + $('#allowGroupSharing').toggleClass('hidden', !this.checked) + }) + + $('#shareapiExcludeGroups').change(() => { + $('#selectExcludedGroups').toggleClass('hidden', !this.checked) + }) + + const setupChecks = () => { + // run setup checks then gather error messages + $.when( + OC.SetupChecks.checkWebDAV(), + OC.SetupChecks.checkWellKnownUrl('GET', '/.well-known/webfinger', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true, [200, 404], true), + OC.SetupChecks.checkWellKnownUrl('GET', '/.well-known/nodeinfo', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true, [200, 404], true), + OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/caldav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), + OC.SetupChecks.checkWellKnownUrl('PROPFIND', '/.well-known/carddav', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), + OC.SetupChecks.checkProviderUrl(OC.getRootPath() + '/ocm-provider/', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), + OC.SetupChecks.checkProviderUrl(OC.getRootPath() + '/ocs-provider/', OC.theme.docPlaceholderUrl, $('#postsetupchecks').data('check-wellknown') === true), + OC.SetupChecks.checkSetup(), + OC.SetupChecks.checkGeneric(), + OC.SetupChecks.checkWOFF2Loading(OC.filePath('core', '', 'fonts/NotoSans-Regular-latin.woff2'), OC.theme.docPlaceholderUrl), + OC.SetupChecks.checkDataProtected() + ).then((check1, check2, check3, check4, check5, check6, check7, check8, check9, check10, check11) => { + const messages = [].concat(check1, check2, check3, check4, check5, check6, check7, check8, check9, check10, check11) + const $el = $('#postsetupchecks') + $('#security-warning-state-loading').addClass('hidden') + + let hasMessages = false + const $errorsEl = $el.find('.errors') + const $warningsEl = $el.find('.warnings') + const $infoEl = $el.find('.info') + + for (let i = 0; i < messages.length; i++) { + switch (messages[i].type) { + case OC.SetupChecks.MESSAGE_TYPE_INFO: + $infoEl.append('<li>' + messages[i].msg + '</li>') + break + case OC.SetupChecks.MESSAGE_TYPE_WARNING: + $warningsEl.append('<li>' + messages[i].msg + '</li>') + break + case OC.SetupChecks.MESSAGE_TYPE_ERROR: + default: + $errorsEl.append('<li>' + messages[i].msg + '</li>') + } + } + + if ($errorsEl.find('li').length > 0) { + $errorsEl.removeClass('hidden') + hasMessages = true + } + if ($warningsEl.find('li').length > 0) { + $warningsEl.removeClass('hidden') + hasMessages = true + } + if ($infoEl.find('li').length > 0) { + $infoEl.removeClass('hidden') + hasMessages = true + } + + if (hasMessages) { + $('#postsetupchecks-hint').removeClass('hidden') + if ($errorsEl.find('li').length > 0) { + $('#security-warning-state-failure').removeClass('hidden') + } else { + $('#security-warning-state-warning').removeClass('hidden') + } + } else { + const securityWarning = $('#security-warning') + if (securityWarning.children('ul').children().length === 0) { + $('#security-warning-state-ok').removeClass('hidden') + } else { + $('#security-warning-state-failure').removeClass('hidden') + } + } + }) + } + + if (document.getElementById('security-warning') !== null) { + setupChecks() + } +}) diff --git a/apps/settings/src/mixins/AppManagement.js b/apps/settings/src/mixins/AppManagement.js index 96f2c1dad4a..cf44a37a53f 100644 --- a/apps/settings/src/mixins/AppManagement.js +++ b/apps/settings/src/mixins/AppManagement.js @@ -20,6 +20,9 @@ * */ +import { showError } from '@nextcloud/dialogs' +import rebuildNavigation from '../service/rebuild-navigation.js' + export default { computed: { appGroups() { @@ -109,33 +112,33 @@ export default { }, forceEnable(appId) { this.$store.dispatch('forceEnableApp', { appId, groups: [] }) - .then((response) => { OC.Settings.Apps.rebuildNavigation() }) - .catch((error) => { OC.Notification.show(error) }) + .then((response) => { rebuildNavigation() }) + .catch((error) => { showError(error) }) }, enable(appId) { this.$store.dispatch('enableApp', { appId, groups: [] }) - .then((response) => { OC.Settings.Apps.rebuildNavigation() }) - .catch((error) => { OC.Notification.show(error) }) + .then((response) => { rebuildNavigation() }) + .catch((error) => { showError(error) }) }, disable(appId) { this.$store.dispatch('disableApp', { appId }) - .then((response) => { OC.Settings.Apps.rebuildNavigation() }) - .catch((error) => { OC.Notification.show(error) }) + .then((response) => { rebuildNavigation() }) + .catch((error) => { showError(error) }) }, remove(appId) { this.$store.dispatch('uninstallApp', { appId }) - .then((response) => { OC.Settings.Apps.rebuildNavigation() }) - .catch((error) => { OC.Notification.show(error) }) + .then((response) => { rebuildNavigation() }) + .catch((error) => { showError(error) }) }, install(appId) { this.$store.dispatch('enableApp', { appId }) - .then((response) => { OC.Settings.Apps.rebuildNavigation() }) - .catch((error) => { OC.Notification.show(error) }) + .then((response) => { rebuildNavigation() }) + .catch((error) => { showError(error) }) }, update(appId) { this.$store.dispatch('updateApp', { appId }) - .then((response) => { OC.Settings.Apps.rebuildNavigation() }) - .catch((error) => { OC.Notification.show(error) }) + .then((response) => { rebuildNavigation() }) + .catch((error) => { showError(error) }) }, }, } diff --git a/apps/settings/src/service/rebuild-navigation.js b/apps/settings/src/service/rebuild-navigation.js new file mode 100644 index 00000000000..57cb1e439bd --- /dev/null +++ b/apps/settings/src/service/rebuild-navigation.js @@ -0,0 +1,130 @@ +import axios from '@nextcloud/axios' +import { generateOcsUrl } from '@nextcloud/router' + +export default () => { + return axios.get(generateOcsUrl('core/navigation', 2) + '/apps?format=json') + .then(({ data }) => { + if (data.ocs.meta.statuscode !== 200) { + return + } + + const addedApps = {} + const navEntries = data.ocs.data + const container = document.querySelector('#navigation #apps ul') + + // remove disabled apps + navEntries.forEach((entry) => { + if (!container.querySelector('li[data-id="' + entry.id + '"]')) { + addedApps[entry.id] = true + } + }) + + container.querySelectorAll('li[data-id]').forEach((el, index) => { + const id = el.dataset.id + // remove all apps that are not in the correct order + if (!navEntries[index] || (navEntries[index] && navEntries[index].id !== id)) { + el.remove() + document.querySelector(`#appmenu li[data-id=${id}]`).remove() + } + }) + + let previousEntry = {} + // add enabled apps to #navigation and #appmenu + navEntries.forEach((entry) => { + if (container.querySelector(`li[data-id="${entry.id}"]`) === null) { + const li = document.createElement('li') + li.dataset.id = entry.id + const img = `<svg width="20" height="20" viewBox="0 0 20 20" alt=""> + <defs> + <filter id="invertMenuMore-${entry.id}"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0"></feColorMatrix></filter> + <mask id="hole"> + <rect width="100%" height="100%" fill="white"></rect> + <circle r="4.5" cx="17" cy="3" fill="black"></circle> + </mask> + </defs> + <image x="0" y="0" width="16" height="16" filter="url(#invertMenuMore-${entry.id})" preserveAspectRatio="xMinYMin meet" xlink:href="${entry.icon}" class="app-icon" /> + </svg>` + + const imgElement = document.createElement('template') + imgElement.innerHTML = img + + const a = document.createElement('a') + a.setAttribute('href', entry.href) + + const filename = document.createElement('span') + filename.appendChild(document.createTextNode(entry.name)) + + const loading = document.createElement('div') + loading.setAttribute('class', 'unread-counter') + loading.style.display = 'none' + + // draw attention to the newly added app entry + // by flashing twice the more apps menu + if (addedApps[entry.id]) { + a.classList.add('animated') + } + + a.prepend(imgElement.content.firstChild, loading, filename) + li.append(a) + + // add app icon to the navigation + const previousElement = document.querySelector(`#navigation li[data-id=${previousEntry.id}]`) + if (previousElement) { + previousElement.insertAdjacentElement('afterend', li) + } else { + document.querySelector('#navigation #apps ul').prepend(li) + } + } + + if (document.getElementById('appmenu').querySelector(`li[data-id="${entry.id}"]`) === null) { + const li = document.createElement('li') + li.dataset.id = entry.id + // Generating svg embedded image (see layout.user.php) + let img + if (OCA.Theming && OCA.Theming.inverted) { + img = `<svg width="20" height="20" viewBox="0 0 20 20" alt=""> + <defs> + <filter id="invert"><feColorMatrix in="SourceGraphic" type="matrix" values="-1 0 0 0 1 0 -1 0 0 1 0 0 -1 0 1 0 0 0 1 0" /></filter> + </defs> + <image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" filter="url(#invert)" xlink:href="${entry.icon}" class="app-icon" /> + </svg>` + } else { + img = `<svg width="20" height="20" viewBox="0 0 20 20" alt=""> + <image x="0" y="0" width="20" height="20" preserveAspectRatio="xMinYMin meet" xlink:href="${entry.icon}" class="app-icon" /> + </svg>` + } + const imgElement = document.createElement('template') + imgElement.innerHTML = img + + const a = document.createElement('a') + a.setAttribute('href', entry.href) + + const filename = document.createElement('span') + filename.appendChild(document.createTextNode(entry.name)) + + const loading = document.createElement('div') + loading.setAttribute('class', 'icon-loading-dark') + loading.style.display = 'none' + + // draw attention to the newly added app entry + // by flashing twice the more apps menu + if (addedApps[entry.id]) { + a.classList.add('animated') + } + + a.prepend(loading, filename, imgElement.content.firstChild) + li.append(a) + + // add app icon to the navigation + const previousElement = document.querySelector('#appmenu li[data-id=' + previousEntry.id + ']') + if (previousElement) { + previousElement.insertAdjacentElement('afterend', li) + } else { + document.queryElementById('appmenu').prepend(li) + } + } + previousEntry = entry + }) + window.dispatchEvent(new Event('resize')) + }) +} diff --git a/apps/settings/src/store/apps.js b/apps/settings/src/store/apps.js index 038b42e64c9..1efed274b32 100644 --- a/apps/settings/src/store/apps.js +++ b/apps/settings/src/store/apps.js @@ -25,6 +25,8 @@ import api from './api' import Vue from 'vue' import { generateUrl } from '@nextcloud/router' +import { showError, showInfo } from '@nextcloud/dialogs' +import '@nextcloud/dialogs/styles/toast.scss' const state = { apps: [], @@ -37,7 +39,7 @@ const state = { const mutations = { APPS_API_FAILURE(state, error) { - OC.Notification.showHtml(t('settings', 'An error occured during the request. Unable to proceed.') + '<br>' + error.error.response.data.data.message, { timeout: 7 }) + showError(t('settings', 'An error occured during the request. Unable to proceed.') + '<br>' + error.error.response.data.data.message, { timeout: 7, isHTML: true }) console.error(state, error) }, @@ -180,16 +182,16 @@ const actions = { return api.get(generateUrl('apps/files')) .then(() => { if (response.data.update_required) { - OC.dialogs.info( + showInfo( t( 'settings', 'The app has been enabled but needs to be updated. You will be redirected to the update page in 5 seconds.' ), - t('settings', 'App update'), - function() { - window.location.reload() - }, - true + { + onClick: () => window.location.reload(), + close: false, + + } ) setTimeout(function() { location.reload() diff --git a/apps/settings/templates/settings/frame.php b/apps/settings/templates/settings/frame.php index 53987bf6074..6d017f07671 100644 --- a/apps/settings/templates/settings/frame.php +++ b/apps/settings/templates/settings/frame.php @@ -22,7 +22,8 @@ */ style('settings', 'settings'); -script('settings', [ 'settings', 'admin', 'log']); +script('settings', 'settings'); +\OCP\Util::addScript('settings', 'legacy-admin'); script('core', 'setupchecks'); script('files', 'jquery.fileupload'); |