diff options
author | Christoph Wurst <christoph@winzerhof-wurst.at> | 2019-12-04 20:18:58 +0100 |
---|---|---|
committer | Roeland Jago Douma <roeland@famdouma.nl> | 2019-12-12 08:13:01 +0100 |
commit | 302558cfd2b3dd37e6332c0d9c650174b64f20fb (patch) | |
tree | 27a7bcbf35f94a496fc2c42c361c79793811418e /core/src | |
parent | 97deaf85b9d18cabfc345025ef273da24006c6de (diff) | |
download | nextcloud-server-302558cfd2b3dd37e6332c0d9c650174b64f20fb.tar.gz nextcloud-server-302558cfd2b3dd37e6332c0d9c650174b64f20fb.zip |
Add a dedicated page for the recommended apps installation
Signed-off-by: Christoph Wurst <christoph@winzerhof-wurst.at>
Signed-off-by: npmbuildbot[bot] <npmbuildbot[bot]@users.noreply.github.com>
Diffstat (limited to 'core/src')
-rw-r--r-- | core/src/components/setup/RecommendedApps.vue | 194 | ||||
-rw-r--r-- | core/src/logger.js | 37 | ||||
-rw-r--r-- | core/src/recommendedapps.js | 44 |
3 files changed, 275 insertions, 0 deletions
diff --git a/core/src/components/setup/RecommendedApps.vue b/core/src/components/setup/RecommendedApps.vue new file mode 100644 index 00000000000..e8f56c8468d --- /dev/null +++ b/core/src/components/setup/RecommendedApps.vue @@ -0,0 +1,194 @@ +<!-- + - @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/>. + --> + +<template> + <div class="update"> + <h2>{{ t('core', 'Recommended apps') }}</h2> + <p v-if="loadingApps" class="loading"> + {{ t('core', 'Loading apps …') }} + </p> + <p v-else-if="loadingAppsError" class="loading-error"> + {{ t('core', 'Could not fetch list of apps from the app store.') }} + </p> + <p v-else> + {{ t('core', 'Installing recommended apps …') }} + </p> + <div v-for="app in recommendedApps" :key="app.id" class="app"> + <img :src="customIcon(app.id)" :alt="t('core', 'Nextcloud app {app}', { app: app.name })"> + <div class="info"> + <h3> + {{ app.name }} + <span v-if="app.loading" class="icon icon-loading-small" /> + <span v-else-if="app.active" class="icon icon-checkmark-white" /> + </h3> + <p v-html="customDescription(app.id)" /> + <p v-if="app.installationError" class="error"> + {{ t('core', 'App download or installation failed') }} + </p> + <p v-else-if="!app.isCompatible" class="error"> + {{ t('core', 'Can\'t install this app because it is not compatible') }} + </p> + <p v-else-if="!app.canInstall" class="error"> + {{ t('core', 'Can\'t install this app') }} + </p> + </div> + </div> + <a :href="defaultPageUrl">{{ t('core', 'Go back') }}</a> + </div> +</template> + +<script> +import axios from '@nextcloud/axios' +import { generateUrl, imagePath } from '@nextcloud/router' +import { loadState } from '@nextcloud/initial-state' +import pLimit from 'p-limit' +import { translate as t } from '@nextcloud/l10n' + +import logger from '../../logger' + +const recommended = { + calendar: { + description: t('core', 'Schedule work & meetings, synced with all your devices.'), + icon: imagePath('core', 'places/calendar.svg') + }, + contacts: { + description: t('core', 'Keep your colleagues and friends in one place without leaking their private info.'), + icon: imagePath('core', 'places/contacts.svg') + }, + mail: { + description: t('core', 'Simple email app nicely integrated with Files, Contacts and Calendar.'), + icon: imagePath('core', 'actions/mail.svg') + }, + talk: { + description: t('core', 'Screensharing, online meetings and web conferencing – on desktop and with mobile apps.') + } +} +const recommendedIds = Object.keys(recommended) +const defaultPageUrl = loadState('core', 'defaultPageUrl') + +export default { + name: 'RecommendedApps', + data() { + return { + loadingApps: true, + loadingAppsError: false, + apps: [], + defaultPageUrl + } + }, + computed: { + recommendedApps() { + return this.apps.filter(app => recommendedIds.includes(app.id)) + } + }, + mounted() { + return axios.get(generateUrl('settings/apps/list')) + .then(resp => resp.data) + .then(data => { + logger.info(`${data.apps.length} apps fetched`) + + this.apps = data.apps.map(app => Object.assign(app, { loading: false, installationError: false })) + logger.debug(`${this.recommendedApps.length} recommended apps found`, { apps: this.recommendedApps }) + + this.installApps() + }) + .catch(error => { + logger.error('could not fetch app list', { error }) + + this.loadingAppsError = true + }) + .then(() => { + this.loadingApps = false + }) + }, + methods: { + installApps() { + const limit = pLimit(1) + const installing = this.recommendedApps + .filter(app => !app.active && app.isCompatible && app.canInstall) + .map(app => limit(() => { + logger.info(`installing ${app.id}`) + app.loading = true + return axios.post(generateUrl(`settings/apps/enable`), { appIds: [app.id], groups: [] }) + .catch(error => { + logger.error(`could not install ${app.id}`, { error }) + app.installationError = true + }) + .then(() => { + logger.info(`installed ${app.id}`) + app.loading = false + }) + })) + logger.debug(`installing ${installing.length} recommended apps`) + Promise.all(installing) + .then(() => { + logger.info('all recommended apps installed, redirecting …') + + window.location = defaultPageUrl + }) + .catch(error => logger.error('could not install recommended apps', { error })) + }, + customIcon(appId) { + if (!(appId in recommended)) { + logger.warn(`no app icon for recommended app ${appId}`) + return imagePath('core', 'places/default-app-icon.svg') + } + return recommended[appId].icon + }, + customDescription(appId) { + if (!(appId in recommended)) { + logger.warn(`no app description for recommended app ${appId}`) + return '' + } + return recommended[appId].description + } + } +} +</script> + +<style lang="scss" scoped> +p.loading, p.loading-error { + height: 100px; +} +.app { + display: flex; + flex-direction: row; + + img { + height: 64px; + width: 64px; + } + + img, .info { + padding: 12px; + } + + .info { + h3 { + text-align: left; + } + + h3 > span.icon { + display: inline-block; + } + } +} +</style> diff --git a/core/src/logger.js b/core/src/logger.js new file mode 100644 index 00000000000..4a9c8623a7f --- /dev/null +++ b/core/src/logger.js @@ -0,0 +1,37 @@ +/* + * @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/>. + */ + +import { getCurrentUser } from '@nextcloud/auth' +import { getLoggerBuilder } from '@nextcloud/logger' + +const getLogger = user => { + if (user === null) { + return getLoggerBuilder() + .setApp('core') + .build() + } + return getLoggerBuilder() + .setApp('core') + .setUid(user.uid) + .build() +} + +export default getLogger(getCurrentUser()) diff --git a/core/src/recommendedapps.js b/core/src/recommendedapps.js new file mode 100644 index 00000000000..ac0afb99daa --- /dev/null +++ b/core/src/recommendedapps.js @@ -0,0 +1,44 @@ +/* + * @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/>. + */ + +import { getRequestToken } from '@nextcloud/auth' +import { generateFilePath } from '@nextcloud/router' +import { translate as t } from '@nextcloud/l10n' +import Vue from 'vue' + +import logger from './logger' +import RecommendedApps from './components/setup/RecommendedApps' + +// eslint-disable-next-line camelcase +__webpack_nonce__ = btoa(getRequestToken()) +// eslint-disable-next-line camelcase +__webpack_public_path__ = generateFilePath('core', '', 'js/') + +Vue.mixin({ + methods: { + t + } +}) + +const View = Vue.extend(RecommendedApps) +new View().$mount('#recommended-apps') + +logger.debug('recommended apps view rendered') |