diff --git a/apps/settings/js/vue-4.js b/apps/settings/js/vue-4.js index be21d10b35e1c81cbd6ac945dcb729e6a53222e0..b2e85769945182a862fdcfa3765efb9df5195c89 100644 Binary files a/apps/settings/js/vue-4.js and b/apps/settings/js/vue-4.js differ diff --git a/apps/settings/js/vue-4.js.map b/apps/settings/js/vue-4.js.map index d78ea55117994640840113ac4e5f206d6defba58..d9b80b7ad159a28f084d023b5820a6e481b3a0a7 100644 Binary files a/apps/settings/js/vue-4.js.map and b/apps/settings/js/vue-4.js.map differ diff --git a/apps/settings/js/vue-5.js b/apps/settings/js/vue-5.js index 8eb491497f46c411f12a9d9aa142e2dd6d51631a..98317284ec1e54385e20c5871e513deb7359d6eb 100644 Binary files a/apps/settings/js/vue-5.js and b/apps/settings/js/vue-5.js differ diff --git a/apps/settings/js/vue-5.js.map b/apps/settings/js/vue-5.js.map index 9f67448e32291599e495d78b269469de3c34ae21..d2fa0760e74879ab5c9f644dc70967065f332a3e 100644 Binary files a/apps/settings/js/vue-5.js.map and b/apps/settings/js/vue-5.js.map differ diff --git a/apps/settings/js/vue-settings-apps-users-management.js b/apps/settings/js/vue-settings-apps-users-management.js index 2bdf60ed261bac37e8ce7a3e8c30424c2ac9ac16..4d813889657f88949f96834e2479ad736f7b90b9 100644 Binary files a/apps/settings/js/vue-settings-apps-users-management.js and b/apps/settings/js/vue-settings-apps-users-management.js differ diff --git a/apps/settings/js/vue-settings-apps-users-management.js.map b/apps/settings/js/vue-settings-apps-users-management.js.map index c5da053eacbba8a78be9158b624adb0fc7d3dc67..25bdfba8f2ead84d74bd25d6d666624bf1236cbc 100644 Binary files a/apps/settings/js/vue-settings-apps-users-management.js.map and b/apps/settings/js/vue-settings-apps-users-management.js.map differ diff --git a/apps/settings/src/components/AppList.vue b/apps/settings/src/components/AppList.vue index a406f6b8ff63e81d44551a6a86118d9598e5e576..f03d7c5a6947b7938c2458a45b380f101fa61257 100644 --- a/apps/settings/src/components/AppList.vue +++ b/apps/settings/src/components/AppList.vue @@ -96,9 +96,11 @@ </template> <script> +import pLimit from 'p-limit' + import AppItem from './AppList/AppItem' import PrefixMixin from './PrefixMixin' -import pLimit from 'p-limit' +import recommended from '../recommendedApps' export default { name: 'AppList', @@ -129,26 +131,26 @@ export default { return OC.Util.naturalSortCompare(sortStringA, sortStringB) }) - if (this.category === 'installed') { + switch (this.category) { + case 'installed': return apps.filter(app => app.installed) - } - if (this.category === 'enabled') { + case 'recommended': + return apps.filter(app => recommended.includes(app.id)) + case 'enabled': return apps.filter(app => app.active && app.installed) - } - if (this.category === 'disabled') { + case 'disabled': return apps.filter(app => !app.active && app.installed) - } - if (this.category === 'app-bundles') { + case 'app-bundles': return apps.filter(app => app.bundles) - } - if (this.category === 'updates') { + case 'updates': return apps.filter(app => app.update) + default: + // filter app store categories + return apps.filter(app => { + return app.appstore && app.category !== undefined + && (app.category === this.category || app.category.indexOf(this.category) > -1) + }) } - // filter app store categories - return apps.filter(app => { - return app.appstore && app.category !== undefined - && (app.category === this.category || app.category.indexOf(this.category) > -1) - }) }, bundles() { return this.$store.getters.getServerData.bundles.filter(bundle => this.bundleApps(bundle.id).length > 0) @@ -175,7 +177,7 @@ export default { return !this.useListView && !this.useBundleView }, useListView() { - return (this.category === 'installed' || this.category === 'enabled' || this.category === 'disabled' || this.category === 'updates') + return ['installed', 'recommended', 'enabled', 'disabled', 'updates'].includes(this.category) }, useBundleView() { return (this.category === 'app-bundles') @@ -196,6 +198,24 @@ export default { } } }, + mounted() { + if (this.category === 'recommended' && 'download' in this.$route.query) { + const limit = pLimit(1) + const installing = this.apps + .filter(app => !app.active && app.canInstall) + .map(app => limit(() => this.$store.dispatch('enableApp', { appId: app.id, groups: [] }))) + console.debug(`installing ${installing.length} recommended apps`) + Promise.all(installing) + .then(() => { + console.info('recommended apps installed') + + if ('returnTo' in this.$route.query) { + window.location = this.$route.query.returnTo + } + }) + .catch(e => console.error('could not install recommended apps', e)) + } + }, methods: { toggleBundle(id) { if (this.allBundlesEnabled(id)) { diff --git a/apps/settings/src/recommendedApps.js b/apps/settings/src/recommendedApps.js new file mode 100644 index 0000000000000000000000000000000000000000..d2868b8728b3c3bca2ee73dc297a213b6186a45b --- /dev/null +++ b/apps/settings/src/recommendedApps.js @@ -0,0 +1,26 @@ +/* + * @copyright 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @author 2019 Christoph Wurst <christoph@winzerhof-wurst.at> + * + * @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/>. + */ + +export default [ + 'contacts', + 'calendar', + 'mail' +] diff --git a/apps/settings/src/views/Apps.vue b/apps/settings/src/views/Apps.vue index 2e0649f7f56555c5f350990ee3890377796301f6..a2c4cae825d0cdf02b153c4f92735e0a6e0c6185 100644 --- a/apps/settings/src/views/Apps.vue +++ b/apps/settings/src/views/Apps.vue @@ -31,7 +31,10 @@ </ul> </AppNavigation> <AppContent class="app-settings-content" :class="{ 'icon-loading': loadingList }"> - <AppList :category="category" :app="currentApp" :search="searchQuery" /> + <AppList v-if="!loadingList" + :category="category" + :app="currentApp" + :search="searchQuery" /> </AppContent> <AppSidebar v-if="id && currentApp" @close="hideAppDetails"> <AppDetails :category="category" :app="currentApp" /> @@ -133,13 +136,21 @@ export default { icon: 'icon-category-installed', text: t('settings', 'Your apps') }, + { + id: 'app-category-recommended', + classes: [], + router: { name: 'apps-category', params: { category: 'recommended' } }, + icon: 'icon-category-installed', + text: t('settings', 'Recommended apps') + }, { id: 'app-category-enabled', classes: [], icon: 'icon-category-enabled', router: { name: 'apps-category', params: { category: 'enabled' } }, text: t('settings', 'Active apps') - }, { + }, + { id: 'app-category-disabled', classes: [], icon: 'icon-category-disabled', diff --git a/core/Controller/SetupController.php b/core/Controller/SetupController.php index 3dd02fc31dc2a914c0f41982e687b75a76b93f44..fd0a68954718d0f5af10156b78d8b2b298e71590 100644 --- a/core/Controller/SetupController.php +++ b/core/Controller/SetupController.php @@ -31,6 +31,7 @@ namespace OC\Core\Controller; use OC\Setup; use OCP\ILogger; +use function urlencode; class SetupController { /** @var Setup */ @@ -76,7 +77,7 @@ class SetupController { $options = array_merge($opts, $post, $errors); $this->display($options); } else { - $this->finishSetup(); + $this->finishSetup(isset($post['install-recommended-apps'])); } } else { $options = array_merge($opts, $post); @@ -105,7 +106,7 @@ class SetupController { \OC_Template::printGuestPage('', 'installation', $parameters); } - public function finishSetup() { + private function finishSetup(bool $installRecommended) { if( file_exists( $this->autoConfigFile )) { unlink($this->autoConfigFile); } @@ -117,6 +118,12 @@ class SetupController { } } + if ($installRecommended) { + $urlGenerator = \OC::$server->getURLGenerator(); + $location = $urlGenerator->getAbsoluteURL('/index.php/settings/apps/recommended?download&returnTo=' . urlencode(\OC_Util::getDefaultPageUrl())); + header('Location: ' . $location); + exit(); + } \OC_Util::redirectToDefaultPage(); } diff --git a/core/js/setup.js b/core/js/setup.js index 5b0bd679dbe82b265541a80a99097274b1c2968f..eb41795e427f1f56506e263a5c2e19b5cf1ae8c4 100644 --- a/core/js/setup.js +++ b/core/js/setup.js @@ -41,8 +41,6 @@ $(document).ready(function() { $('#dbname').attr('pattern','[0-9a-zA-Z$_-.]+'); }); - $('input[checked]').trigger('click'); - $('#showAdvanced').click(function(e) { e.preventDefault(); $('#datadirContent').slideToggle(250); diff --git a/core/templates/installation.php b/core/templates/installation.php index de9427a74d8dd42e35095d923c2cb1cc529183aa..bdc06c540860e7c1e8a4f0235fbdd9f16e0e5c93 100644 --- a/core/templates/installation.php +++ b/core/templates/installation.php @@ -158,6 +158,15 @@ script('core', [ </fieldset> <?php endif ?> + <fieldset> + <p class="info"> + <input type="checkbox" id="install-recommended-apps" name="install-recommended-apps" class="checkbox checkbox--white" checked> + <label for="install-recommended-apps"> + <?php p($l->t( 'Install recommended apps' )); ?> + </label> + </p> + </fieldset> + <div class="icon-loading-dark float-spinner"> </div> <div class="buttons"><input type="submit" class="primary" value="<?php p($l->t( 'Finish setup' )); ?>" data-finishing="<?php p($l->t( 'Finishing …' )); ?>"></div>