2323 <div class =" body-login-container" >
2424 <h2 >{{ t('core', 'Recommended apps') }}</h2 >
2525 <p v-if =" loadingApps" class =" loading text-center" >
26- {{ t('core', 'Loading apps …') }}
26+ {{ t('core', 'Installing apps …') }}
2727 </p >
2828 <p v-else-if =" loadingAppsError" class =" loading-error text-center" >
2929 {{ t('core', 'Could not fetch list of apps from the App Store.') }}
3030 </p >
31- <p v-else class =" text-center" >
32- {{ t('core', 'Installing apps …') }}
33- </p >
3431 <div v-for =" app in recommendedApps" :key =" app.id" class =" app" >
3532 <img :src =" customIcon(app.id)" alt =" " >
3633 <div class =" info" >
5148 </p >
5249 </div >
5350 </div >
51+
52+ <InstallButton v-if =" showInstallButton"
53+ @click.stop.prevent =" installRecommendedApps" />
54+
5455 <p class =" text-center" >
5556 <a :href =" defaultPageUrl" >{{ t('core', 'Cancel') }}</a >
5657 </p >
@@ -64,6 +65,9 @@ import { loadState } from '@nextcloud/initial-state'
6465import pLimit from ' p-limit'
6566import { translate as t } from ' @nextcloud/l10n'
6667
68+ // TODO replace with Button component when @nextcloud/vue is upgraded to v5
69+ import InstallButton from ' ./InstallButton'
70+
6771import logger from ' ../../logger'
6872
6973const recommended = {
@@ -97,9 +101,13 @@ const defaultPageUrl = loadState('core', 'defaultPageUrl')
97101
98102export default {
99103 name: ' RecommendedApps' ,
104+ components: {
105+ InstallButton,
106+ },
100107 data () {
101108 return {
102- loadingApps: true ,
109+ showInstallButton: true ,
110+ loadingApps: false ,
103111 loadingAppsError: false ,
104112 apps: [],
105113 defaultPageUrl,
@@ -110,27 +118,30 @@ export default {
110118 return this .apps .filter (app => recommendedIds .includes (app .id ))
111119 },
112120 },
113- mounted () {
114- return axios .get (generateUrl (' settings/apps/list' ))
115- .then (resp => resp .data )
116- .then (data => {
117- logger .info (` ${ data .apps .length } apps fetched` )
118-
119- this .apps = data .apps .map (app => Object .assign (app, { loading: false , installationError: false }))
120- logger .debug (` ${ this .recommendedApps .length } recommended apps found` , { apps: this .recommendedApps })
121-
122- this .installApps ()
123- })
124- .catch (error => {
125- logger .error (' could not fetch app list' , { error })
126-
127- this .loadingAppsError = true
128- })
129- .then (() => {
130- this .loadingApps = false
131- })
132- },
133121 methods: {
122+ installRecommendedApps () {
123+ this .showInstallButton = false
124+ this .loadingApps = true
125+
126+ return axios .get (generateUrl (' settings/apps/list' ))
127+ .then (resp => resp .data )
128+ .then (data => {
129+ logger .info (` ${ data .apps .length } apps fetched` )
130+
131+ this .apps = data .apps .map (app => Object .assign (app, { loading: false , installationError: false }))
132+ logger .debug (` ${ this .recommendedApps .length } recommended apps found` , { apps: this .recommendedApps })
133+
134+ this .installApps ()
135+ })
136+ .catch (error => {
137+ logger .error (' could not fetch app list' , { error })
138+
139+ this .loadingAppsError = true
140+ })
141+ .then (() => {
142+ this .loadingApps = false
143+ })
144+ },
134145 installApps () {
135146 const limit = pLimit (1 )
136147 const installing = this .recommendedApps
0 commit comments