aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/cypress.yml48
-rw-r--r--core/src/components/setup/RecommendedApps.vue6
-rw-r--r--cypress.config.ts24
-rw-r--r--cypress/dockerNode.ts25
-rw-r--r--cypress/e2e/core/setup.ts114
-rw-r--r--dist/core-recommendedapps.js4
-rw-r--r--dist/core-recommendedapps.js.map2
7 files changed, 207 insertions, 16 deletions
diff --git a/.github/workflows/cypress.yml b/.github/workflows/cypress.yml
index bc079cd4e9a..bd8298678a0 100644
--- a/.github/workflows/cypress.yml
+++ b/.github/workflows/cypress.yml
@@ -94,11 +94,56 @@ jobs:
matrix:
# Run multiple copies of the current job in parallel
# Please increase the number or runners as your tests suite grows (0 based index for e2e tests)
- containers: ["component", '0', '1', '2', '3', '4', '5', '6', '7']
+ containers: ['component', 'setup', '0', '1', '2', '3', '4', '5', '6', '7']
# Hack as strategy.job-total includes the component and GitHub does not allow math expressions
# Always align this number with the total of e2e runners (max. index + 1)
total-containers: [8]
+ services:
+ mysql:
+ # Only start mysql if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-mysql-8.4:latest' || ''}}
+ ports:
+ - '3306/tcp'
+ env:
+ MYSQL_ROOT_PASSWORD: rootpassword
+ MYSQL_USER: oc_autotest
+ MYSQL_PASSWORD: nextcloud
+ MYSQL_DATABASE: oc_autotest
+ options: --health-cmd="mysqladmin ping" --health-interval 5s --health-timeout 2s --health-retries 10
+
+ mariadb:
+ # Only start mariadb if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'mariadb:11.4' || ''}}
+ ports:
+ - '3306/tcp'
+ env:
+ MYSQL_ROOT_PASSWORD: rootpassword
+ MYSQL_USER: oc_autotest
+ MYSQL_PASSWORD: nextcloud
+ MYSQL_DATABASE: oc_autotest
+ options: --health-cmd="mariadb-admin ping" --health-interval 5s --health-timeout 2s --health-retries 5
+
+ postgres:
+ # Only start postgres if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'ghcr.io/nextcloud/continuous-integration-postgres-17:latest' || ''}}
+ ports:
+ - '5432/tcp'
+ env:
+ POSTGRES_USER: root
+ POSTGRES_PASSWORD: rootpassword
+ POSTGRES_DB: nextcloud
+ options: --mount type=tmpfs,destination=/var/lib/postgresql/data --health-cmd pg_isready --health-interval 5s --health-timeout 2s --health-retries 5
+
+ oracle:
+ # Only start oracle if we are running the setup tests
+ image: ${{matrix.containers == 'setup' && 'ghcr.io/gvenzl/oracle-free:23' || ''}}
+ ports:
+ - '1521'
+ env:
+ ORACLE_PASSWORD: oracle
+ options: --health-cmd healthcheck.sh --health-interval 20s --health-timeout 10s --health-retries 10
+
name: runner ${{ matrix.containers }}
steps:
@@ -141,6 +186,7 @@ jobs:
CYPRESS_RECORD_KEY: ${{ secrets.CYPRESS_RECORD_KEY }}
SPLIT: ${{ matrix.total-containers }}
SPLIT_INDEX: ${{ matrix.containers == 'component' && 0 || matrix.containers }}
+ SETUP_TESTING: ${{ matrix.containers == 'setup' && 'true' || '' }}
- name: Upload snapshots and videos
uses: actions/upload-artifact@ea165f8d65b6e75b540449e92b4886f43607fa02 # v4.6.2
diff --git a/core/src/components/setup/RecommendedApps.vue b/core/src/components/setup/RecommendedApps.vue
index aaad6d93476..b31e4b54ca4 100644
--- a/core/src/components/setup/RecommendedApps.vue
+++ b/core/src/components/setup/RecommendedApps.vue
@@ -4,7 +4,7 @@
-->
<template>
- <div class="guest-box">
+ <div class="guest-box" data-cy-setup-recommended-apps>
<h2>{{ t('core', 'Recommended apps') }}</h2>
<p v-if="loadingApps" class="loading text-center">
{{ t('core', 'Loading apps …') }}
@@ -40,13 +40,15 @@
<NcButton v-if="showInstallButton && !installingApps"
type="tertiary"
role="link"
- :href="defaultPageUrl">
+ :href="defaultPageUrl"
+ data-cy-setup-recommended-apps-skip>
{{ t('core', 'Skip') }}
</NcButton>
<NcButton v-if="showInstallButton"
type="primary"
:disabled="installingApps || !isAnyAppSelected"
+ data-cy-setup-recommended-apps-install>
@click.stop.prevent="installApps">
{{ installingApps ? t('core', 'Installing apps …') : t('core', 'Install recommended apps') }}
</NcButton>
diff --git a/cypress.config.ts b/cypress.config.ts
index 1e83c0b7f5d..0b1a0524c9d 100644
--- a/cypress.config.ts
+++ b/cypress.config.ts
@@ -3,6 +3,13 @@
* SPDX-License-Identifier: AGPL-3.0-or-later
*/
import type { Configuration } from 'webpack'
+import { defineConfig } from 'cypress'
+import { join } from 'path'
+import { removeDirectory } from 'cypress-delete-downloads-folder'
+
+import cypressSplit from 'cypress-split'
+import webpackPreprocessor from '@cypress/webpack-preprocessor'
+
import {
applyChangesToNextcloud,
configureNextcloud,
@@ -10,11 +17,6 @@ import {
stopNextcloud,
waitOnNextcloud,
} from './cypress/dockerNode'
-import { defineConfig } from 'cypress'
-import cypressSplit from 'cypress-split'
-import { removeDirectory } from 'cypress-delete-downloads-folder'
-import webpackPreprocessor from '@cypress/webpack-preprocessor'
-
import webpackConfig from './webpack.config.js'
export default defineConfig({
@@ -62,8 +64,6 @@ export default defineConfig({
// We've imported your old cypress plugins here.
// You may want to clean this up later by importing these.
async setupNodeEvents(on, config) {
- cypressSplit(on, config)
-
on('file:preprocessor', webpackPreprocessor({ webpackOptions: webpackConfig as Configuration }))
on('task', { removeDirectory })
@@ -106,6 +106,16 @@ export default defineConfig({
}
})
+ // Check if we are running the setup checks
+ if (process.env.SETUP_TESTING === 'true') {
+ console.log('Adding setup tests to specPattern 🧮')
+ config.specPattern = [join(__dirname, 'cypress/e2e/core/setup.ts')]
+ console.log('└─ Done')
+ } else {
+ // If we are not running the setup tests, we need to remove the setup tests from the specPattern
+ cypressSplit(on, config)
+ }
+
// Before the browser launches
// starting Nextcloud testing container
const ip = await startNextcloud(process.env.BRANCH)
diff --git a/cypress/dockerNode.ts b/cypress/dockerNode.ts
index b65f164dc15..5cd2415f111 100644
--- a/cypress/dockerNode.ts
+++ b/cypress/dockerNode.ts
@@ -94,6 +94,9 @@ export const startNextcloud = async function(branch: string = getCurrentGitBranc
HostPort: '8083',
}],
},
+ // If running the setup tests, let's bind to host
+ // to communicate with the github actions DB services
+ NetworkMode: process.env.SETUP_TESTING === 'true' ? await getGithubNetwork() : undefined,
},
Env: [
`BRANCH=${branch}`,
@@ -106,9 +109,6 @@ export const startNextcloud = async function(branch: string = getCurrentGitBranc
await runExec(container, ['chown', '-R', 'www-data:www-data', '/var/www/html/data'], false, 'root')
await runExec(container, ['chmod', '0770', '/var/www/html/data'], false, 'root')
- // Init Nextcloud
- // await runExec(container, ['initnc.sh'], true, 'root')
-
// Get container's IP
const ip = await getContainerIP(container)
@@ -252,6 +252,7 @@ export const getContainerIP = async function(
if (err) {
throw err
}
+
if (data?.HostConfig.PortBindings?.['80/tcp']?.[0]?.HostPort) {
ip = `localhost:${data.HostConfig.PortBindings['80/tcp'][0].HostPort}`
} else {
@@ -335,3 +336,21 @@ const sleep = function(milliseconds: number) {
const getCurrentGitBranch = function() {
return execSync('git rev-parse --abbrev-ref HEAD').toString().trim() || 'master'
}
+
+/**
+ * Get the network name of the github actions network
+ * This is used to connect to the database services
+ * started by github actions
+ */
+const getGithubNetwork = async function(): Promise<string|undefined> {
+ console.log('├─ Looking for github actions network... 🔍')
+ const networks = await docker.listNetworks()
+ const network = networks.find((network) => network.Name.startsWith('github_network'))
+ if (network) {
+ console.log('│ └─ Found github actions network: ' + network.Name)
+ return network.Name
+ }
+
+ console.log('│ └─ No github actions network found')
+ return undefined
+}
diff --git a/cypress/e2e/core/setup.ts b/cypress/e2e/core/setup.ts
new file mode 100644
index 00000000000..01606a75617
--- /dev/null
+++ b/cypress/e2e/core/setup.ts
@@ -0,0 +1,114 @@
+/**
+ * SPDX-FileCopyrightText: 2025 Nextcloud GmbH and Nextcloud contributors
+ * SPDX-License-Identifier: AGPL-3.0-or-later
+ */
+
+/**
+ * DO NOT RENAME THIS FILE to .cy.ts ⚠️
+ * This is not following the pattern of the other files in this folder
+ * because it is manually added to the tests by the cypress config.
+ */
+describe('Can install Nextcloud', { testIsolation: true, retries: 0 }, () => {
+ beforeEach(() => {
+ // Move the config file and data folder
+ cy.runCommand('rm /var/www/html/config/config.php', { failOnNonZeroExit: false })
+ cy.runCommand('rm /var/www/html/data/owncloud.db', { failOnNonZeroExit: false })
+ })
+
+ it('Sqlite', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-sqlite"] input').check({ force: true })
+
+ sharedSetup()
+ })
+
+ it('MySQL', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-mysql"] input').check({ force: true })
+
+ // Fill in the DB form
+ cy.get('[data-cy-setup-form-field="dbuser"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbpass"]').type('{selectAll}nextcloud')
+ cy.get('[data-cy-setup-form-field="dbname"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbhost"]').type('{selectAll}mysql:3306')
+
+ sharedSetup()
+ })
+
+ it('MariaDB', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-mysql"] input').check({ force: true })
+
+ // Fill in the DB form
+ cy.get('[data-cy-setup-form-field="dbuser"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbpass"]').type('{selectAll}nextcloud')
+ cy.get('[data-cy-setup-form-field="dbname"]').type('{selectAll}oc_autotest')
+ cy.get('[data-cy-setup-form-field="dbhost"]').type('{selectAll}mariadb:3306')
+
+ sharedSetup()
+ })
+
+ it('PostgreSQL', () => {
+ cy.visit('/')
+ cy.get('[data-cy-setup-form]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminlogin"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="adminpass"]').should('be.visible')
+ cy.get('[data-cy-setup-form-field="directory"]').should('have.value', '/var/www/html/data')
+
+ // Select the SQLite database
+ cy.get('[data-cy-setup-form-field="dbtype-pgsql"] input').check({ force: true })
+
+ // Fill in the DB form
+ cy.get('[data-cy-setup-form-field="dbuser"]').type('{selectAll}root')
+ cy.get('[data-cy-setup-form-field="dbpass"]').type('{selectAll}rootpassword')
+ cy.get('[data-cy-setup-form-field="dbname"]').type('{selectAll}nextcloud')
+ cy.get('[data-cy-setup-form-field="dbhost"]').type('{selectAll}postgres:5432')
+
+ sharedSetup()
+ })
+
+})
+
+/**
+ * Shared admin setup function for the Nextcloud setup
+ */
+function sharedSetup() {
+ const randAdmin = 'admin-' + Math.random().toString(36).substring(2, 15)
+
+ // Fill in the form
+ cy.get('[data-cy-setup-form-field="adminlogin"]').type(randAdmin)
+ cy.get('[data-cy-setup-form-field="adminpass"]').type(randAdmin)
+
+ // Nothing more to do on sqlite, let's continue
+ cy.get('[data-cy-setup-form-submit]').click()
+
+ // Wait for the setup to finish
+ cy.location('pathname', { timeout: 10000 })
+ .should('include', '/core/apps/recommended')
+
+ // Skip the setup apps
+ cy.get('[data-cy-setup-recommended-apps]').should('be.visible')
+ cy.get('[data-cy-setup-recommended-apps-skip]').click()
+
+ // Go to files
+ cy.visit('/apps/files/')
+ cy.get('[data-cy-files-content]').should('be.visible')
+}
diff --git a/dist/core-recommendedapps.js b/dist/core-recommendedapps.js
index 073705a5999..71d8d449059 100644
--- a/dist/core-recommendedapps.js
+++ b/dist/core-recommendedapps.js
@@ -1,2 +1,2 @@
-(()=>{"use strict";var t,e={12665:(t,e,n)=>{n.d(e,{A:()=>s});var i=n(71354),o=n.n(i),r=n(76314),a=n.n(r)()(o());a.push([t.id,".dialog-row[data-v-07178674]{display:flex;justify-content:end;margin-top:8px}p.loading[data-v-07178674],p.loading-error[data-v-07178674]{height:100px}p[data-v-07178674]:last-child{margin-top:10px}.text-center[data-v-07178674]{text-align:center}.app[data-v-07178674]{display:flex;flex-direction:row}.app img[data-v-07178674]{height:50px;width:50px;filter:var(--background-invert-if-dark)}.app img[data-v-07178674],.app .info[data-v-07178674]{padding:12px}.app .info h3[data-v-07178674],.app .info p[data-v-07178674]{text-align:start}.app .info h3[data-v-07178674]{margin-top:0}.app .checkbox-radio-switch[data-v-07178674]{margin-inline-start:auto;padding:0 2px}","",{version:3,sources:["webpack://./core/src/components/setup/RecommendedApps.vue"],names:[],mappings:"AACA,6BACC,YAAA,CACA,mBAAA,CACA,cAAA,CAIA,4DAEC,YAAA,CAGD,8BACC,eAAA,CAIF,8BACC,iBAAA,CAGD,sBACC,YAAA,CACA,kBAAA,CAEA,0BACC,WAAA,CACA,UAAA,CACA,uCAAA,CAGD,sDACC,YAAA,CAIA,6DACC,gBAAA,CAGD,+BACC,YAAA,CAIF,6CACC,wBAAA,CACA,aAAA",sourcesContent:["\n.dialog-row {\n\tdisplay: flex;\n\tjustify-content: end;\n\tmargin-top: 8px;\n}\n\np {\n\t&.loading,\n\t&.loading-error {\n\t\theight: 100px;\n\t}\n\n\t&:last-child {\n\t\tmargin-top: 10px;\n\t}\n}\n\n.text-center {\n\ttext-align: center;\n}\n\n.app {\n\tdisplay: flex;\n\tflex-direction: row;\n\n\timg {\n\t\theight: 50px;\n\t\twidth: 50px;\n\t\tfilter: var(--background-invert-if-dark);\n\t}\n\n\timg, .info {\n\t\tpadding: 12px;\n\t}\n\n\t.info {\n\t\th3, p {\n\t\t\ttext-align: start;\n\t\t}\n\n\t\th3 {\n\t\t\tmargin-top: 0;\n\t\t}\n\t}\n\n\t.checkbox-radio-switch {\n\t\tmargin-inline-start: auto;\n\t\tpadding: 0 2px;\n\t}\n}\n"],sourceRoot:""}]);const s=a},93376:(t,e,n)=>{var i=n(21777),o=n(53334),r=n(85471),a=n(35947);const s=null===(c=(0,i.HW)())?(0,a.YK)().setApp("core").build():(0,a.YK)().setApp("core").setUid(c.uid).build();var c;(0,a.YK)().setApp("unified-search").detectUser().build();var l=n(32981),p=n(63814),d=n(65043);function u(t,e,n){(function(t,e){if(e.has(t))throw new TypeError("Cannot initialize the same private elements twice on an object")})(t,e),e.set(t,n)}function h(t,e,n){return t.set(m(t,e),n),n}function A(t,e){return t.get(m(t,e))}function m(t,e,n){if("function"==typeof t?t===e:t.has(e))return arguments.length<3?e:n;throw new TypeError("Private element is not present on this object")}function g(t,e,n){return(e=function(t){var e=function(t){if("object"!=typeof t||!t)return t;var e=t[Symbol.toPrimitive];if(void 0!==e){var n=e.call(t,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(t)}(t);return"symbol"==typeof e?e:e+""}(e))in t?Object.defineProperty(t,e,{value:n,enumerable:!0,configurable:!0,writable:!0}):t[e]=n,t}class v{constructor(t){g(this,"value",void 0),g(this,"next",void 0),this.value=t}}var f=new WeakMap,C=new WeakMap,b=new WeakMap;class y{constructor(){u(this,f,void 0),u(this,C,void 0),u(this,b,void 0),this.clear()}enqueue(t){var e;const n=new v(t);A(f,this)?(A(C,this).next=n,h(C,this,n)):(h(f,this,n),h(C,this,n)),h(b,this,(e=A(b,this),++e))}dequeue(){var t;const e=A(f,this);if(e)return h(f,this,A(f,this).next),h(b,this,(t=A(b,this),--t)),e.value}peek(){if(A(f,this))return A(f,this).value}clear(){h(f,this,void 0),h(C,this,void 0),h(b,this,0)}get size(){return A(b,this)}*[Symbol.iterator](){let t=A(f,this);for(;t;)yield t.value,t=t.next}}function w(t){x(t);const e=new y;let n=0;const i=()=>{n<t&&e.size>0&&(e.dequeue()(),n++)},o=async(t,e,o)=>{const r=(async()=>t(...o))();e(r);try{await r}catch{}n--,i()},r=function(r){for(var a=arguments.length,s=new Array(a>1?a-1:0),c=1;c<a;c++)s[c-1]=arguments[c];return new Promise((a=>{((r,a,s)=>{new Promise((t=>{e.enqueue(t)})).then(o.bind(void 0,r,a,s)),(async()=>{await Promise.resolve(),n<t&&i()})()})(r,a,s)}))};return Object.defineProperties(r,{activeCount:{get:()=>n},pendingCount:{get:()=>e.size},clearQueue:{value(){e.clear()}},concurrency:{get:()=>t,set(o){x(o),t=o,queueMicrotask((()=>{for(;n<t&&e.size>0;)i()}))}}}),r}function x(t){if(!Number.isInteger(t)&&t!==Number.POSITIVE_INFINITY||!(t>0))throw new TypeError("Expected `concurrency` to be a number from 1 and up")}var _=n(97012),k=n(32073);const S={calendar:{description:(0,o.t)("core","Schedule work & meetings, synced with all your devices."),icon:(0,p.d0)("core","places/calendar.svg")},contacts:{description:(0,o.t)("core","Keep your colleagues and friends in one place without leaking their private info."),icon:(0,p.d0)("core","places/contacts.svg")},mail:{description:(0,o.t)("core","Simple email app nicely integrated with Files, Contacts and Calendar."),icon:(0,p.d0)("core","actions/mail.svg")},spreed:{description:(0,o.t)("core","Chatting, video calls, screen sharing, online meetings and web conferencing – in your browser and with mobile apps."),icon:(0,p.d0)("core","apps/spreed.svg")},richdocuments:{name:"Nextcloud Office",description:(0,o.t)("core","Collaborative documents, spreadsheets and presentations, built on Collabora Online."),icon:(0,p.d0)("core","apps/richdocuments.svg")},notes:{description:(0,o.t)("core","Distraction free note taking app."),icon:(0,p.d0)("core","apps/notes.svg")},richdocumentscode:{hidden:!0}},I=Object.keys(S),P={name:"RecommendedApps",components:{NcCheckboxRadioSwitch:k.A,NcButton:_.A},data:()=>({showInstallButton:!1,installingApps:!1,loadingApps:!0,loadingAppsError:!1,apps:[],defaultPageUrl:(0,l.C)("core","defaultPageUrl")}),computed:{recommendedApps(){return this.apps.filter((t=>I.includes(t.id)))},isAnyAppSelected(){return this.recommendedApps.some((t=>t.isSelected))}},async mounted(){try{const{data:t}=await d.Ay.get((0,p.Jv)("settings/apps/list"));s.info(`${t.apps.length} apps fetched`),this.apps=t.apps.map((t=>Object.assign(t,{loading:!1,installationError:!1,isSelected:t.isCompatible}))),s.debug(`${this.recommendedApps.length} recommended apps found`,{apps:this.recommendedApps}),this.showInstallButton=!0}catch(t){s.error("could not fetch app list",{error:t}),this.loadingAppsError=!0}finally{this.loadingApps=!1}},methods:{installApps(){this.installingApps=!0;const t=w(1),e=this.recommendedApps.filter((t=>!t.active&&t.isCompatible&&t.canInstall&&t.isSelected)).map((e=>t((async()=>(s.info(`installing ${e.id}`),e.loading=!0,d.Ay.post((0,p.Jv)("settings/apps/enable"),{appIds:[e.id],groups:[]}).catch((t=>{s.error(`could not install ${e.id}`,{error:t}),e.isSelected=!1,e.installationError=!0})).then((()=>{s.info(`installed ${e.id}`),e.loading=!1,e.active=!0})))))));s.debug(`installing ${e.length} recommended apps`),Promise.all(e).then((()=>{s.info("all recommended apps installed, redirecting …"),window.location=this.defaultPageUrl})).catch((t=>s.error("could not install recommended apps",{error:t})))},customIcon:t=>t in S&&S[t].icon?S[t].icon:(s.warn(`no app icon for recommended app ${t}`),(0,p.d0)("core","places/default-app-icon.svg")),customName:t=>t.id in S&&S[t.id].name||t.name,customDescription:t=>t in S?S[t].description:(s.warn(`no app description for recommended app ${t}`),""),isHidden:t=>t in S&&!!S[t].hidden,toggleSelect(t){if(!(t in S)||!this.showInstallButton)return;const e=this.apps.findIndex((e=>e.id===t));this.$set(this.apps[e],"isSelected",!this.apps[e].isSelected)}}};var O=n(85072),j=n.n(O),B=n(97825),E=n.n(B),T=n(77659),N=n.n(T),D=n(55056),$=n.n(D),Y=n(10540),U=n.n(Y),M=n(41113),R=n.n(M),q=n(12665),z={};z.styleTagTransform=R(),z.setAttributes=$(),z.insert=N().bind(null,"head"),z.domAPI=E(),z.insertStyleElement=U(),j()(q.A,z),q.A&&q.A.locals&&q.A.locals;const F=(0,n(14486).A)(P,(function(){var t=this,e=t._self._c;return e("div",{staticClass:"guest-box"},[e("h2",[t._v(t._s(t.t("core","Recommended apps")))]),t._v(" "),t.loadingApps?e("p",{staticClass:"loading text-center"},[t._v("\n\t\t"+t._s(t.t("core","Loading apps …"))+"\n\t")]):t.loadingAppsError?e("p",{staticClass:"loading-error text-center"},[t._v("\n\t\t"+t._s(t.t("core","Could not fetch list of apps from the App Store."))+"\n\t")]):t._e(),t._v(" "),t._l(t.recommendedApps,(function(n){return e("div",{key:n.id,staticClass:"app"},[t.isHidden(n.id)?t._e():[e("img",{attrs:{src:t.customIcon(n.id),alt:""}}),t._v(" "),e("div",{staticClass:"info"},[e("h3",[t._v(t._s(t.customName(n)))]),t._v(" "),e("p",{domProps:{textContent:t._s(t.customDescription(n.id))}}),t._v(" "),n.installationError?e("p",[e("strong",[t._v(t._s(t.t("core","App download or installation failed")))])]):n.isCompatible?n.canInstall?t._e():e("p",[e("strong",[t._v(t._s(t.t("core","Cannot install this app")))])]):e("p",[e("strong",[t._v(t._s(t.t("core","Cannot install this app because it is not compatible")))])])]),t._v(" "),e("NcCheckboxRadioSwitch",{attrs:{checked:n.isSelected||n.active,disabled:!n.isCompatible||n.active,loading:n.loading},on:{"update:checked":function(e){return t.toggleSelect(n.id)}}})]],2)})),t._v(" "),e("div",{staticClass:"dialog-row"},[t.showInstallButton&&!t.installingApps?e("NcButton",{attrs:{type:"tertiary",role:"link",href:t.defaultPageUrl}},[t._v("\n\t\t\t"+t._s(t.t("core","Skip"))+"\n\t\t")]):t._e(),t._v(" "),t.showInstallButton?e("NcButton",{attrs:{type:"primary",disabled:t.installingApps||!t.isAnyAppSelected},on:{click:function(e){return e.stopPropagation(),e.preventDefault(),t.installApps.apply(null,arguments)}}},[t._v("\n\t\t\t"+t._s(t.installingApps?t.t("core","Installing apps …"):t.t("core","Install recommended apps"))+"\n\t\t")]):t._e()],1)],2)}),[],!1,null,"07178674",null).exports;n.nc=(0,i.aV)(),r.Ay.mixin({methods:{t:o.Tl}}),(new(r.Ay.extend(F))).$mount("#recommended-apps"),s.debug("recommended apps view rendered")}},n={};function i(t){var o=n[t];if(void 0!==o)return o.exports;var r=n[t]={id:t,loaded:!1,exports:{}};return e[t].call(r.exports,r,r.exports,i),r.loaded=!0,r.exports}i.m=e,t=[],i.O=(e,n,o,r)=>{if(!n){var a=1/0;for(p=0;p<t.length;p++){n=t[p][0],o=t[p][1],r=t[p][2];for(var s=!0,c=0;c<n.length;c++)(!1&r||a>=r)&&Object.keys(i.O).every((t=>i.O[t](n[c])))?n.splice(c--,1):(s=!1,r<a&&(a=r));if(s){t.splice(p--,1);var l=o();void 0!==l&&(e=l)}}return e}r=r||0;for(var p=t.length;p>0&&t[p-1][2]>r;p--)t[p]=t[p-1];t[p]=[n,o,r]},i.n=t=>{var e=t&&t.__esModule?()=>t.default:()=>t;return i.d(e,{a:e}),e},i.d=(t,e)=>{for(var n in e)i.o(e,n)&&!i.o(t,n)&&Object.defineProperty(t,n,{enumerable:!0,get:e[n]})},i.e=()=>Promise.resolve(),i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(t){if("object"==typeof window)return window}}(),i.o=(t,e)=>Object.prototype.hasOwnProperty.call(t,e),i.r=t=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(t,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(t,"__esModule",{value:!0})},i.nmd=t=>(t.paths=[],t.children||(t.children=[]),t),i.j=2696,(()=>{i.b=document.baseURI||self.location.href;var t={2696:0};i.O.j=e=>0===t[e];var e=(e,n)=>{var o,r,a=n[0],s=n[1],c=n[2],l=0;if(a.some((e=>0!==t[e]))){for(o in s)i.o(s,o)&&(i.m[o]=s[o]);if(c)var p=c(i)}for(e&&e(n);l<a.length;l++)r=a[l],i.o(t,r)&&t[r]&&t[r][0](),t[r]=0;return i.O(p)},n=self.webpackChunknextcloud=self.webpackChunknextcloud||[];n.forEach(e.bind(null,0)),n.push=e.bind(null,n.push.bind(n))})(),i.nc=void 0;var o=i.O(void 0,[4208],(()=>i(93376)));o=i.O(o)})();
-//# sourceMappingURL=core-recommendedapps.js.map?v=7eba92eea8c86411a9a5 \ No newline at end of file
+(()=>{"use strict";var e,t={10440:(e,t,n)=>{var i=n(21777),o=n(53334),a=n(85471),r=n(35947);const s=null===(c=(0,i.HW)())?(0,r.YK)().setApp("core").build():(0,r.YK)().setApp("core").setUid(c.uid).build();var c;(0,r.YK)().setApp("unified-search").detectUser().build();var p=n(32981),l=n(63814),d=n(65043);function u(e,t,n){(function(e,t){if(t.has(e))throw new TypeError("Cannot initialize the same private elements twice on an object")})(e,t),t.set(e,n)}function h(e,t,n){return e.set(A(e,t),n),n}function m(e,t){return e.get(A(e,t))}function A(e,t,n){if("function"==typeof e?e===t:e.has(t))return arguments.length<3?t:n;throw new TypeError("Private element is not present on this object")}function g(e,t,n){return(t=function(e){var t=function(e){if("object"!=typeof e||!e)return e;var t=e[Symbol.toPrimitive];if(void 0!==t){var n=t.call(e,"string");if("object"!=typeof n)return n;throw new TypeError("@@toPrimitive must return a primitive value.")}return String(e)}(e);return"symbol"==typeof t?t:t+""}(t))in e?Object.defineProperty(e,t,{value:n,enumerable:!0,configurable:!0,writable:!0}):e[t]=n,e}class v{constructor(e){g(this,"value",void 0),g(this,"next",void 0),this.value=e}}var f=new WeakMap,b=new WeakMap,C=new WeakMap;class y{constructor(){u(this,f,void 0),u(this,b,void 0),u(this,C,void 0),this.clear()}enqueue(e){var t;const n=new v(e);m(f,this)?(m(b,this).next=n,h(b,this,n)):(h(f,this,n),h(b,this,n)),h(C,this,(t=m(C,this),++t))}dequeue(){var e;const t=m(f,this);if(t)return h(f,this,m(f,this).next),h(C,this,(e=m(C,this),--e)),t.value}peek(){if(m(f,this))return m(f,this).value}clear(){h(f,this,void 0),h(b,this,void 0),h(C,this,0)}get size(){return m(C,this)}*[Symbol.iterator](){let e=m(f,this);for(;e;)yield e.value,e=e.next}}function w(e){x(e);const t=new y;let n=0;const i=()=>{n<e&&t.size>0&&(t.dequeue()(),n++)},o=async(e,t,o)=>{const a=(async()=>e(...o))();t(a);try{await a}catch{}n--,i()},a=function(a){for(var r=arguments.length,s=new Array(r>1?r-1:0),c=1;c<r;c++)s[c-1]=arguments[c];return new Promise((r=>{((a,r,s)=>{new Promise((e=>{t.enqueue(e)})).then(o.bind(void 0,a,r,s)),(async()=>{await Promise.resolve(),n<e&&i()})()})(a,r,s)}))};return Object.defineProperties(a,{activeCount:{get:()=>n},pendingCount:{get:()=>t.size},clearQueue:{value(){t.clear()}},concurrency:{get:()=>e,set(o){x(o),e=o,queueMicrotask((()=>{for(;n<e&&t.size>0;)i()}))}}}),a}function x(e){if(!Number.isInteger(e)&&e!==Number.POSITIVE_INFINITY||!(e>0))throw new TypeError("Expected `concurrency` to be a number from 1 and up")}var _=n(97012),k=n(32073);const S={calendar:{description:(0,o.t)("core","Schedule work & meetings, synced with all your devices."),icon:(0,l.d0)("core","places/calendar.svg")},contacts:{description:(0,o.t)("core","Keep your colleagues and friends in one place without leaking their private info."),icon:(0,l.d0)("core","places/contacts.svg")},mail:{description:(0,o.t)("core","Simple email app nicely integrated with Files, Contacts and Calendar."),icon:(0,l.d0)("core","actions/mail.svg")},spreed:{description:(0,o.t)("core","Chatting, video calls, screen sharing, online meetings and web conferencing – in your browser and with mobile apps."),icon:(0,l.d0)("core","apps/spreed.svg")},richdocuments:{name:"Nextcloud Office",description:(0,o.t)("core","Collaborative documents, spreadsheets and presentations, built on Collabora Online."),icon:(0,l.d0)("core","apps/richdocuments.svg")},notes:{description:(0,o.t)("core","Distraction free note taking app."),icon:(0,l.d0)("core","apps/notes.svg")},richdocumentscode:{hidden:!0}},I=Object.keys(S),P={name:"RecommendedApps",components:{NcCheckboxRadioSwitch:k.A,NcButton:_.A},data:()=>({showInstallButton:!1,installingApps:!1,loadingApps:!0,loadingAppsError:!1,apps:[],defaultPageUrl:(0,p.C)("core","defaultPageUrl")}),computed:{recommendedApps(){return this.apps.filter((e=>I.includes(e.id)))},isAnyAppSelected(){return this.recommendedApps.some((e=>e.isSelected))}},async mounted(){try{const{data:e}=await d.Ay.get((0,l.Jv)("settings/apps/list"));s.info(`${e.apps.length} apps fetched`),this.apps=e.apps.map((e=>Object.assign(e,{loading:!1,installationError:!1,isSelected:e.isCompatible}))),s.debug(`${this.recommendedApps.length} recommended apps found`,{apps:this.recommendedApps}),this.showInstallButton=!0}catch(e){s.error("could not fetch app list",{error:e}),this.loadingAppsError=!0}finally{this.loadingApps=!1}},methods:{installApps(){this.installingApps=!0;const e=w(1),t=this.recommendedApps.filter((e=>!e.active&&e.isCompatible&&e.canInstall&&e.isSelected)).map((t=>e((async()=>(s.info(`installing ${t.id}`),t.loading=!0,d.Ay.post((0,l.Jv)("settings/apps/enable"),{appIds:[t.id],groups:[]}).catch((e=>{s.error(`could not install ${t.id}`,{error:e}),t.isSelected=!1,t.installationError=!0})).then((()=>{s.info(`installed ${t.id}`),t.loading=!1,t.active=!0})))))));s.debug(`installing ${t.length} recommended apps`),Promise.all(t).then((()=>{s.info("all recommended apps installed, redirecting …"),window.location=this.defaultPageUrl})).catch((e=>s.error("could not install recommended apps",{error:e})))},customIcon:e=>e in S&&S[e].icon?S[e].icon:(s.warn(`no app icon for recommended app ${e}`),(0,l.d0)("core","places/default-app-icon.svg")),customName:e=>e.id in S&&S[e.id].name||e.name,customDescription:e=>e in S?S[e].description:(s.warn(`no app description for recommended app ${e}`),""),isHidden:e=>e in S&&!!S[e].hidden,toggleSelect(e){if(!(e in S)||!this.showInstallButton)return;const t=this.apps.findIndex((t=>t.id===e));this.$set(this.apps[t],"isSelected",!this.apps[t].isSelected)}}};var O=n(85072),j=n.n(O),B=n(97825),E=n.n(B),T=n(77659),N=n.n(T),D=n(55056),$=n.n(D),Y=n(10540),U=n.n(Y),M=n(41113),R=n.n(M),q=n(43823),z={};z.styleTagTransform=R(),z.setAttributes=$(),z.insert=N().bind(null,"head"),z.domAPI=E(),z.insertStyleElement=U(),j()(q.A,z),q.A&&q.A.locals&&q.A.locals;const F=(0,n(14486).A)(P,(function(){var e=this,t=e._self._c;return t("div",{staticClass:"guest-box",attrs:{"data-cy-setup-recommended-apps":""}},[t("h2",[e._v(e._s(e.t("core","Recommended apps")))]),e._v(" "),e.loadingApps?t("p",{staticClass:"loading text-center"},[e._v("\n\t\t"+e._s(e.t("core","Loading apps …"))+"\n\t")]):e.loadingAppsError?t("p",{staticClass:"loading-error text-center"},[e._v("\n\t\t"+e._s(e.t("core","Could not fetch list of apps from the App Store."))+"\n\t")]):e._e(),e._v(" "),e._l(e.recommendedApps,(function(n){return t("div",{key:n.id,staticClass:"app"},[e.isHidden(n.id)?e._e():[t("img",{attrs:{src:e.customIcon(n.id),alt:""}}),e._v(" "),t("div",{staticClass:"info"},[t("h3",[e._v(e._s(e.customName(n)))]),e._v(" "),t("p",{domProps:{textContent:e._s(e.customDescription(n.id))}}),e._v(" "),n.installationError?t("p",[t("strong",[e._v(e._s(e.t("core","App download or installation failed")))])]):n.isCompatible?n.canInstall?e._e():t("p",[t("strong",[e._v(e._s(e.t("core","Cannot install this app")))])]):t("p",[t("strong",[e._v(e._s(e.t("core","Cannot install this app because it is not compatible")))])])]),e._v(" "),t("NcCheckboxRadioSwitch",{attrs:{checked:n.isSelected||n.active,disabled:!n.isCompatible||n.active,loading:n.loading},on:{"update:checked":function(t){return e.toggleSelect(n.id)}}})]],2)})),e._v(" "),t("div",{staticClass:"dialog-row"},[e.showInstallButton&&!e.installingApps?t("NcButton",{attrs:{type:"tertiary",role:"link",href:e.defaultPageUrl,"data-cy-setup-recommended-apps-skip":""}},[e._v("\n\t\t\t"+e._s(e.t("core","Skip"))+"\n\t\t")]):e._e(),e._v(" "),e.showInstallButton?t("NcButton",{attrs:{type:"primary",disabled:e.installingApps||!e.isAnyAppSelected,"data-cy-setup-recommended-apps-install":""}},[e._v('\n\t\t\t@click.stop.prevent="installApps">\n\t\t\t'+e._s(e.installingApps?e.t("core","Installing apps …"):e.t("core","Install recommended apps"))+"\n\t\t")]):e._e()],1)],2)}),[],!1,null,"5b5c8ecc",null).exports;n.nc=(0,i.aV)(),a.Ay.mixin({methods:{t:o.Tl}}),(new(a.Ay.extend(F))).$mount("#recommended-apps"),s.debug("recommended apps view rendered")},43823:(e,t,n)=>{n.d(t,{A:()=>s});var i=n(71354),o=n.n(i),a=n(76314),r=n.n(a)()(o());r.push([e.id,".dialog-row[data-v-5b5c8ecc]{display:flex;justify-content:end;margin-top:8px}p.loading[data-v-5b5c8ecc],p.loading-error[data-v-5b5c8ecc]{height:100px}p[data-v-5b5c8ecc]:last-child{margin-top:10px}.text-center[data-v-5b5c8ecc]{text-align:center}.app[data-v-5b5c8ecc]{display:flex;flex-direction:row}.app img[data-v-5b5c8ecc]{height:50px;width:50px;filter:var(--background-invert-if-dark)}.app img[data-v-5b5c8ecc],.app .info[data-v-5b5c8ecc]{padding:12px}.app .info h3[data-v-5b5c8ecc],.app .info p[data-v-5b5c8ecc]{text-align:start}.app .info h3[data-v-5b5c8ecc]{margin-top:0}.app .checkbox-radio-switch[data-v-5b5c8ecc]{margin-inline-start:auto;padding:0 2px}","",{version:3,sources:["webpack://./core/src/components/setup/RecommendedApps.vue"],names:[],mappings:"AACA,6BACC,YAAA,CACA,mBAAA,CACA,cAAA,CAIA,4DAEC,YAAA,CAGD,8BACC,eAAA,CAIF,8BACC,iBAAA,CAGD,sBACC,YAAA,CACA,kBAAA,CAEA,0BACC,WAAA,CACA,UAAA,CACA,uCAAA,CAGD,sDACC,YAAA,CAIA,6DACC,gBAAA,CAGD,+BACC,YAAA,CAIF,6CACC,wBAAA,CACA,aAAA",sourcesContent:["\n.dialog-row {\n\tdisplay: flex;\n\tjustify-content: end;\n\tmargin-top: 8px;\n}\n\np {\n\t&.loading,\n\t&.loading-error {\n\t\theight: 100px;\n\t}\n\n\t&:last-child {\n\t\tmargin-top: 10px;\n\t}\n}\n\n.text-center {\n\ttext-align: center;\n}\n\n.app {\n\tdisplay: flex;\n\tflex-direction: row;\n\n\timg {\n\t\theight: 50px;\n\t\twidth: 50px;\n\t\tfilter: var(--background-invert-if-dark);\n\t}\n\n\timg, .info {\n\t\tpadding: 12px;\n\t}\n\n\t.info {\n\t\th3, p {\n\t\t\ttext-align: start;\n\t\t}\n\n\t\th3 {\n\t\t\tmargin-top: 0;\n\t\t}\n\t}\n\n\t.checkbox-radio-switch {\n\t\tmargin-inline-start: auto;\n\t\tpadding: 0 2px;\n\t}\n}\n"],sourceRoot:""}]);const s=r}},n={};function i(e){var o=n[e];if(void 0!==o)return o.exports;var a=n[e]={id:e,loaded:!1,exports:{}};return t[e].call(a.exports,a,a.exports,i),a.loaded=!0,a.exports}i.m=t,e=[],i.O=(t,n,o,a)=>{if(!n){var r=1/0;for(l=0;l<e.length;l++){n=e[l][0],o=e[l][1],a=e[l][2];for(var s=!0,c=0;c<n.length;c++)(!1&a||r>=a)&&Object.keys(i.O).every((e=>i.O[e](n[c])))?n.splice(c--,1):(s=!1,a<r&&(r=a));if(s){e.splice(l--,1);var p=o();void 0!==p&&(t=p)}}return t}a=a||0;for(var l=e.length;l>0&&e[l-1][2]>a;l--)e[l]=e[l-1];e[l]=[n,o,a]},i.n=e=>{var t=e&&e.__esModule?()=>e.default:()=>e;return i.d(t,{a:t}),t},i.d=(e,t)=>{for(var n in t)i.o(t,n)&&!i.o(e,n)&&Object.defineProperty(e,n,{enumerable:!0,get:t[n]})},i.e=()=>Promise.resolve(),i.g=function(){if("object"==typeof globalThis)return globalThis;try{return this||new Function("return this")()}catch(e){if("object"==typeof window)return window}}(),i.o=(e,t)=>Object.prototype.hasOwnProperty.call(e,t),i.r=e=>{"undefined"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:"Module"}),Object.defineProperty(e,"__esModule",{value:!0})},i.nmd=e=>(e.paths=[],e.children||(e.children=[]),e),i.j=2696,(()=>{i.b=document.baseURI||self.location.href;var e={2696:0};i.O.j=t=>0===e[t];var t=(t,n)=>{var o,a,r=n[0],s=n[1],c=n[2],p=0;if(r.some((t=>0!==e[t]))){for(o in s)i.o(s,o)&&(i.m[o]=s[o]);if(c)var l=c(i)}for(t&&t(n);p<r.length;p++)a=r[p],i.o(e,a)&&e[a]&&e[a][0](),e[a]=0;return i.O(l)},n=self.webpackChunknextcloud=self.webpackChunknextcloud||[];n.forEach(t.bind(null,0)),n.push=t.bind(null,n.push.bind(n))})(),i.nc=void 0;var o=i.O(void 0,[4208],(()=>i(10440)));o=i.O(o)})();
+//# sourceMappingURL=core-recommendedapps.js.map?v=22a85edc85db40d68272 \ No newline at end of file
diff --git a/dist/core-recommendedapps.js.map b/dist/core-recommendedapps.js.map
index 0f9f44c3652..54514078a70 100644
--- a/dist/core-recommendedapps.js.map
+++ b/dist/core-recommendedapps.js.map
@@ -1 +1 @@
-{"version":3,"file":"core-recommendedapps.js?v=7eba92eea8c86411a9a5","mappings":"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","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/core/src/components/setup/RecommendedApps.vue?vue&type=style&index=0&id=07178674&prod&lang=scss&scoped=true","webpack:///nextcloud/core/src/logger.js","webpack://nextcloud/./core/src/components/setup/RecommendedApps.vue?5f06","webpack:///nextcloud/node_modules/yocto-queue/index.js","webpack:///nextcloud/node_modules/p-limit/index.js","webpack:///nextcloud/core/src/components/setup/RecommendedApps.vue","webpack:///nextcloud/core/src/components/setup/RecommendedApps.vue?vue&type=script&lang=js","webpack://nextcloud/./core/src/components/setup/RecommendedApps.vue?ff8d","webpack://nextcloud/./core/src/components/setup/RecommendedApps.vue?84e8","webpack:///nextcloud/core/src/recommendedapps.js","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/ensure chunk","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.dialog-row[data-v-07178674]{display:flex;justify-content:end;margin-top:8px}p.loading[data-v-07178674],p.loading-error[data-v-07178674]{height:100px}p[data-v-07178674]:last-child{margin-top:10px}.text-center[data-v-07178674]{text-align:center}.app[data-v-07178674]{display:flex;flex-direction:row}.app img[data-v-07178674]{height:50px;width:50px;filter:var(--background-invert-if-dark)}.app img[data-v-07178674],.app .info[data-v-07178674]{padding:12px}.app .info h3[data-v-07178674],.app .info p[data-v-07178674]{text-align:start}.app .info h3[data-v-07178674]{margin-top:0}.app .checkbox-radio-switch[data-v-07178674]{margin-inline-start:auto;padding:0 2px}`, \"\",{\"version\":3,\"sources\":[\"webpack://./core/src/components/setup/RecommendedApps.vue\"],\"names\":[],\"mappings\":\"AACA,6BACC,YAAA,CACA,mBAAA,CACA,cAAA,CAIA,4DAEC,YAAA,CAGD,8BACC,eAAA,CAIF,8BACC,iBAAA,CAGD,sBACC,YAAA,CACA,kBAAA,CAEA,0BACC,WAAA,CACA,UAAA,CACA,uCAAA,CAGD,sDACC,YAAA,CAIA,6DACC,gBAAA,CAGD,+BACC,YAAA,CAIF,6CACC,wBAAA,CACA,aAAA\",\"sourcesContent\":[\"\\n.dialog-row {\\n\\tdisplay: flex;\\n\\tjustify-content: end;\\n\\tmargin-top: 8px;\\n}\\n\\np {\\n\\t&.loading,\\n\\t&.loading-error {\\n\\t\\theight: 100px;\\n\\t}\\n\\n\\t&:last-child {\\n\\t\\tmargin-top: 10px;\\n\\t}\\n}\\n\\n.text-center {\\n\\ttext-align: center;\\n}\\n\\n.app {\\n\\tdisplay: flex;\\n\\tflex-direction: row;\\n\\n\\timg {\\n\\t\\theight: 50px;\\n\\t\\twidth: 50px;\\n\\t\\tfilter: var(--background-invert-if-dark);\\n\\t}\\n\\n\\timg, .info {\\n\\t\\tpadding: 12px;\\n\\t}\\n\\n\\t.info {\\n\\t\\th3, p {\\n\\t\\t\\ttext-align: start;\\n\\t\\t}\\n\\n\\t\\th3 {\\n\\t\\t\\tmargin-top: 0;\\n\\t\\t}\\n\\t}\\n\\n\\t.checkbox-radio-switch {\\n\\t\\tmargin-inline-start: auto;\\n\\t\\tpadding: 0 2px;\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","/**\n * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { getLoggerBuilder } from '@nextcloud/logger'\n\nconst getLogger = user => {\n\tif (user === null) {\n\t\treturn getLoggerBuilder()\n\t\t\t.setApp('core')\n\t\t\t.build()\n\t}\n\treturn getLoggerBuilder()\n\t\t.setApp('core')\n\t\t.setUid(user.uid)\n\t\t.build()\n}\n\nexport default getLogger(getCurrentUser())\n\nexport const unifiedSearchLogger = getLoggerBuilder()\n\t.setApp('unified-search')\n\t.detectUser()\n\t.build()\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"guest-box\"},[_c('h2',[_vm._v(_vm._s(_vm.t('core', 'Recommended apps')))]),_vm._v(\" \"),(_vm.loadingApps)?_c('p',{staticClass:\"loading text-center\"},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('core', 'Loading apps …'))+\"\\n\\t\")]):(_vm.loadingAppsError)?_c('p',{staticClass:\"loading-error text-center\"},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('core', 'Could not fetch list of apps from the App Store.'))+\"\\n\\t\")]):_vm._e(),_vm._v(\" \"),_vm._l((_vm.recommendedApps),function(app){return _c('div',{key:app.id,staticClass:\"app\"},[(!_vm.isHidden(app.id))?[_c('img',{attrs:{\"src\":_vm.customIcon(app.id),\"alt\":\"\"}}),_vm._v(\" \"),_c('div',{staticClass:\"info\"},[_c('h3',[_vm._v(_vm._s(_vm.customName(app)))]),_vm._v(\" \"),_c('p',{domProps:{\"textContent\":_vm._s(_vm.customDescription(app.id))}}),_vm._v(\" \"),(app.installationError)?_c('p',[_c('strong',[_vm._v(_vm._s(_vm.t('core', 'App download or installation failed')))])]):(!app.isCompatible)?_c('p',[_c('strong',[_vm._v(_vm._s(_vm.t('core', 'Cannot install this app because it is not compatible')))])]):(!app.canInstall)?_c('p',[_c('strong',[_vm._v(_vm._s(_vm.t('core', 'Cannot install this app')))])]):_vm._e()]),_vm._v(\" \"),_c('NcCheckboxRadioSwitch',{attrs:{\"checked\":app.isSelected || app.active,\"disabled\":!app.isCompatible || app.active,\"loading\":app.loading},on:{\"update:checked\":function($event){return _vm.toggleSelect(app.id)}}})]:_vm._e()],2)}),_vm._v(\" \"),_c('div',{staticClass:\"dialog-row\"},[(_vm.showInstallButton && !_vm.installingApps)?_c('NcButton',{attrs:{\"type\":\"tertiary\",\"role\":\"link\",\"href\":_vm.defaultPageUrl}},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('core', 'Skip'))+\"\\n\\t\\t\")]):_vm._e(),_vm._v(\" \"),(_vm.showInstallButton)?_c('NcButton',{attrs:{\"type\":\"primary\",\"disabled\":_vm.installingApps || !_vm.isAnyAppSelected},on:{\"click\":function($event){$event.stopPropagation();$event.preventDefault();return _vm.installApps.apply(null, arguments)}}},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.installingApps ? _vm.t('core', 'Installing apps …') : _vm.t('core', 'Install recommended apps'))+\"\\n\\t\\t\")]):_vm._e()],1)],2)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n}\n","import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tqueue.dequeue()();\n\t\t\t// Since `pendingCount` has been decreased by one, increase `activeCount` by one.\n\t\t\tactiveCount++;\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\tresolve(result);\n\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue `internalResolve` instead of the `run` function\n\t\t// to preserve asynchronous context.\n\t\tnew Promise(internalResolve => {\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(\n\t\t\trun.bind(undefined, function_, resolve, arguments_),\n\t\t);\n\n\t\t(async () => {\n\t\t\t// This function needs to wait until the next microtask before comparing\n\t\t\t// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously\n\t\t\t// after the `internalResolve` function is dequeued and called. The comparison in the if-statement\n\t\t\t// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.\n\t\t\tawait Promise.resolve();\n\n\t\t\tif (activeCount < concurrency) {\n\t\t\t\tresumeNext();\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, option) {\n\tconst {concurrency} = option;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n","<!--\n - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<template>\n\t<div class=\"guest-box\">\n\t\t<h2>{{ t('core', 'Recommended apps') }}</h2>\n\t\t<p v-if=\"loadingApps\" class=\"loading text-center\">\n\t\t\t{{ t('core', 'Loading apps …') }}\n\t\t</p>\n\t\t<p v-else-if=\"loadingAppsError\" class=\"loading-error text-center\">\n\t\t\t{{ t('core', 'Could not fetch list of apps from the App Store.') }}\n\t\t</p>\n\n\t\t<div v-for=\"app in recommendedApps\" :key=\"app.id\" class=\"app\">\n\t\t\t<template v-if=\"!isHidden(app.id)\">\n\t\t\t\t<img :src=\"customIcon(app.id)\" alt=\"\">\n\t\t\t\t<div class=\"info\">\n\t\t\t\t\t<h3>{{ customName(app) }}</h3>\n\t\t\t\t\t<p v-text=\"customDescription(app.id)\" />\n\t\t\t\t\t<p v-if=\"app.installationError\">\n\t\t\t\t\t\t<strong>{{ t('core', 'App download or installation failed') }}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t\t<p v-else-if=\"!app.isCompatible\">\n\t\t\t\t\t\t<strong>{{ t('core', 'Cannot install this app because it is not compatible') }}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t\t<p v-else-if=\"!app.canInstall\">\n\t\t\t\t\t\t<strong>{{ t('core', 'Cannot install this app') }}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<NcCheckboxRadioSwitch :checked=\"app.isSelected || app.active\"\n\t\t\t\t\t:disabled=\"!app.isCompatible || app.active\"\n\t\t\t\t\t:loading=\"app.loading\"\n\t\t\t\t\t@update:checked=\"toggleSelect(app.id)\" />\n\t\t\t</template>\n\t\t</div>\n\n\t\t<div class=\"dialog-row\">\n\t\t\t<NcButton v-if=\"showInstallButton && !installingApps\"\n\t\t\t\ttype=\"tertiary\"\n\t\t\t\trole=\"link\"\n\t\t\t\t:href=\"defaultPageUrl\">\n\t\t\t\t{{ t('core', 'Skip') }}\n\t\t\t</NcButton>\n\n\t\t\t<NcButton v-if=\"showInstallButton\"\n\t\t\t\ttype=\"primary\"\n\t\t\t\t:disabled=\"installingApps || !isAnyAppSelected\"\n\t\t\t\t@click.stop.prevent=\"installApps\">\n\t\t\t\t{{ installingApps ? t('core', 'Installing apps …') : t('core', 'Install recommended apps') }}\n\t\t\t</NcButton>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { t } from '@nextcloud/l10n'\nimport { loadState } from '@nextcloud/initial-state'\nimport { generateUrl, imagePath } from '@nextcloud/router'\nimport axios from '@nextcloud/axios'\nimport pLimit from 'p-limit'\nimport logger from '../../logger.js'\n\nimport NcButton from '@nextcloud/vue/components/NcButton'\nimport NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'\n\nconst recommended = {\n\tcalendar: {\n\t\tdescription: t('core', 'Schedule work & meetings, synced with all your devices.'),\n\t\ticon: imagePath('core', 'places/calendar.svg'),\n\t},\n\tcontacts: {\n\t\tdescription: t('core', 'Keep your colleagues and friends in one place without leaking their private info.'),\n\t\ticon: imagePath('core', 'places/contacts.svg'),\n\t},\n\tmail: {\n\t\tdescription: t('core', 'Simple email app nicely integrated with Files, Contacts and Calendar.'),\n\t\ticon: imagePath('core', 'actions/mail.svg'),\n\t},\n\tspreed: {\n\t\tdescription: t('core', 'Chatting, video calls, screen sharing, online meetings and web conferencing – in your browser and with mobile apps.'),\n\t\ticon: imagePath('core', 'apps/spreed.svg'),\n\t},\n\trichdocuments: {\n\t\tname: 'Nextcloud Office',\n\t\tdescription: t('core', 'Collaborative documents, spreadsheets and presentations, built on Collabora Online.'),\n\t\ticon: imagePath('core', 'apps/richdocuments.svg'),\n\t},\n\tnotes: {\n\t\tdescription: t('core', 'Distraction free note taking app.'),\n\t\ticon: imagePath('core', 'apps/notes.svg'),\n\t},\n\trichdocumentscode: {\n\t\thidden: true,\n\t},\n}\nconst recommendedIds = Object.keys(recommended)\n\nexport default {\n\tname: 'RecommendedApps',\n\tcomponents: {\n\t\tNcCheckboxRadioSwitch,\n\t\tNcButton,\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tshowInstallButton: false,\n\t\t\tinstallingApps: false,\n\t\t\tloadingApps: true,\n\t\t\tloadingAppsError: false,\n\t\t\tapps: [],\n\t\t\tdefaultPageUrl: loadState('core', 'defaultPageUrl'),\n\t\t}\n\t},\n\tcomputed: {\n\t\trecommendedApps() {\n\t\t\treturn this.apps.filter(app => recommendedIds.includes(app.id))\n\t\t},\n\t\tisAnyAppSelected() {\n\t\t\treturn this.recommendedApps.some(app => app.isSelected)\n\t\t},\n\t},\n\tasync mounted() {\n\t\ttry {\n\t\t\tconst { data } = await axios.get(generateUrl('settings/apps/list'))\n\t\t\tlogger.info(`${data.apps.length} apps fetched`)\n\n\t\t\tthis.apps = data.apps.map(app => Object.assign(app, { loading: false, installationError: false, isSelected: app.isCompatible }))\n\t\t\tlogger.debug(`${this.recommendedApps.length} recommended apps found`, { apps: this.recommendedApps })\n\n\t\t\tthis.showInstallButton = true\n\t\t} catch (error) {\n\t\t\tlogger.error('could not fetch app list', { error })\n\n\t\t\tthis.loadingAppsError = true\n\t\t} finally {\n\t\t\tthis.loadingApps = false\n\t\t}\n\t},\n\tmethods: {\n\t\tinstallApps() {\n\t\t\tthis.installingApps = true\n\n\t\t\tconst limit = pLimit(1)\n\t\t\tconst installing = this.recommendedApps\n\t\t\t\t.filter(app => !app.active && app.isCompatible && app.canInstall && app.isSelected)\n\t\t\t\t.map(app => limit(async () => {\n\t\t\t\t\tlogger.info(`installing ${app.id}`)\n\t\t\t\t\tapp.loading = true\n\t\t\t\t\treturn axios.post(generateUrl('settings/apps/enable'), { appIds: [app.id], groups: [] })\n\t\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\t\tlogger.error(`could not install ${app.id}`, { error })\n\t\t\t\t\t\t\tapp.isSelected = false\n\t\t\t\t\t\t\tapp.installationError = true\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\tlogger.info(`installed ${app.id}`)\n\t\t\t\t\t\t\tapp.loading = false\n\t\t\t\t\t\t\tapp.active = true\n\t\t\t\t\t\t})\n\t\t\t\t}))\n\t\t\tlogger.debug(`installing ${installing.length} recommended apps`)\n\t\t\tPromise.all(installing)\n\t\t\t\t.then(() => {\n\t\t\t\t\tlogger.info('all recommended apps installed, redirecting …')\n\n\t\t\t\t\twindow.location = this.defaultPageUrl\n\t\t\t\t})\n\t\t\t\t.catch(error => logger.error('could not install recommended apps', { error }))\n\t\t},\n\t\tcustomIcon(appId) {\n\t\t\tif (!(appId in recommended) || !recommended[appId].icon) {\n\t\t\t\tlogger.warn(`no app icon for recommended app ${appId}`)\n\t\t\t\treturn imagePath('core', 'places/default-app-icon.svg')\n\t\t\t}\n\t\t\treturn recommended[appId].icon\n\t\t},\n\t\tcustomName(app) {\n\t\t\tif (!(app.id in recommended)) {\n\t\t\t\treturn app.name\n\t\t\t}\n\t\t\treturn recommended[app.id].name || app.name\n\t\t},\n\t\tcustomDescription(appId) {\n\t\t\tif (!(appId in recommended)) {\n\t\t\t\tlogger.warn(`no app description for recommended app ${appId}`)\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn recommended[appId].description\n\t\t},\n\t\tisHidden(appId) {\n\t\t\tif (!(appId in recommended)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !!recommended[appId].hidden\n\t\t},\n\t\ttoggleSelect(appId) {\n\t\t\t// disable toggle when installButton is disabled\n\t\t\tif (!(appId in recommended) || !this.showInstallButton) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst index = this.apps.findIndex(app => app.id === appId)\n\t\t\tthis.$set(this.apps[index], 'isSelected', !this.apps[index].isSelected)\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.dialog-row {\n\tdisplay: flex;\n\tjustify-content: end;\n\tmargin-top: 8px;\n}\n\np {\n\t&.loading,\n\t&.loading-error {\n\t\theight: 100px;\n\t}\n\n\t&:last-child {\n\t\tmargin-top: 10px;\n\t}\n}\n\n.text-center {\n\ttext-align: center;\n}\n\n.app {\n\tdisplay: flex;\n\tflex-direction: row;\n\n\timg {\n\t\theight: 50px;\n\t\twidth: 50px;\n\t\tfilter: var(--background-invert-if-dark);\n\t}\n\n\timg, .info {\n\t\tpadding: 12px;\n\t}\n\n\t.info {\n\t\th3, p {\n\t\t\ttext-align: start;\n\t\t}\n\n\t\th3 {\n\t\t\tmargin-top: 0;\n\t\t}\n\t}\n\n\t.checkbox-radio-switch {\n\t\tmargin-inline-start: auto;\n\t\tpadding: 0 2px;\n\t}\n}\n</style>\n","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=script&lang=js\"","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=style&index=0&id=07178674&prod&lang=scss&scoped=true\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\noptions.insert = insertFn.bind(null, \"head\");\noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=style&index=0&id=07178674&prod&lang=scss&scoped=true\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./RecommendedApps.vue?vue&type=template&id=07178674&scoped=true\"\nimport script from \"./RecommendedApps.vue?vue&type=script&lang=js\"\nexport * from \"./RecommendedApps.vue?vue&type=script&lang=js\"\nimport style0 from \"./RecommendedApps.vue?vue&type=style&index=0&id=07178674&prod&lang=scss&scoped=true\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"07178674\",\n null\n \n)\n\nexport default component.exports","/**\n * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getCSPNonce } from '@nextcloud/auth'\nimport { translate as t } from '@nextcloud/l10n'\nimport Vue from 'vue'\n\nimport logger from './logger.js'\nimport RecommendedApps from './components/setup/RecommendedApps.vue'\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = getCSPNonce()\n\nVue.mixin({\n\tmethods: {\n\t\tt,\n\t},\n})\n\nconst View = Vue.extend(RecommendedApps)\nnew View().$mount('#recommended-apps')\n\nlogger.debug('recommended apps view rendered')\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","// The chunk loading function for additional chunks\n// Since all referenced chunks are already included\n// in this file, this function is empty here.\n__webpack_require__.e = () => (Promise.resolve());","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 2696;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t2696: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [4208], () => (__webpack_require__(93376)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","___CSS_LOADER_EXPORT___","push","module","id","user","getCurrentUser","getLoggerBuilder","setApp","build","setUid","uid","detectUser","Node","constructor","value","_defineProperty","this","_head","WeakMap","_tail","_size","Queue","_classPrivateFieldInitSpec","clear","enqueue","_this$size","node","_classPrivateFieldGet","next","_classPrivateFieldSet","dequeue","_this$size3","current","peek","undefined","size","Symbol","iterator","pLimit","concurrency","validateConcurrency","queue","activeCount","resumeNext","run","async","function_","resolve","arguments_","result","generator","_len","arguments","length","Array","_key","Promise","internalResolve","then","bind","Object","defineProperties","get","pendingCount","clearQueue","set","newConcurrency","queueMicrotask","Number","isInteger","POSITIVE_INFINITY","TypeError","recommended","calendar","description","t","icon","imagePath","contacts","mail","spreed","richdocuments","name","notes","richdocumentscode","hidden","recommendedIds","keys","components","NcCheckboxRadioSwitch","NcButton","data","showInstallButton","installingApps","loadingApps","loadingAppsError","apps","defaultPageUrl","loadState","computed","recommendedApps","filter","app","includes","isAnyAppSelected","some","isSelected","mounted","axios","generateUrl","logger","info","map","assign","loading","installationError","isCompatible","debug","error","methods","installApps","limit","installing","active","canInstall","post","appIds","groups","catch","all","window","location","customIcon","appId","warn","customName","customDescription","isHidden","toggleSelect","index","findIndex","$set","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","locals","_vm","_c","_self","staticClass","_v","_s","_e","_l","key","attrs","domProps","on","$event","stopPropagation","preventDefault","apply","__webpack_nonce__","getCSPNonce","Vue","mixin","extend","RecommendedApps","$mount","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","loaded","__webpack_modules__","call","m","O","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","every","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","e","g","globalThis","Function","obj","prop","prototype","hasOwnProperty","toStringTag","nmd","paths","children","b","document","baseURI","self","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","chunkLoadingGlobal","forEach","nc","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file
+{"version":3,"file":"core-recommendedapps.js?v=22a85edc85db40d68272","mappings":"uBAAIA,E,mECQJ,MAYA,EAXc,QADIC,GAYOC,EAAAA,EAAAA,QAVhBC,EAAAA,EAAAA,MACLC,OAAO,QACPC,SAEIF,EAAAA,EAAAA,MACLC,OAAO,QACPE,OAAOL,EAAKM,KACZF,QATeJ,OAciBE,EAAAA,EAAAA,MACjCC,OAAO,kBACPI,aACAH,QCzBF,I,2zBCKA,MAAMI,EAILC,WAAAA,CAAYC,GAAOC,EAAA,qBAAAA,EAAA,oBAClBC,KAAKF,MAAQA,CACd,EACA,IAAAG,EAAA,IAAAC,QAAAC,EAAA,IAAAD,QAAAE,EAAA,IAAAF,QAEc,MAAMG,EAKpBR,WAAAA,GAJAS,EAAA,KAAAL,OAAK,GACLK,EAAA,KAAAH,OAAK,GACLG,EAAA,KAAAF,OAAK,GAGJJ,KAAKO,OACN,CAEAC,OAAAA,CAAQV,GAAO,IAAAW,EACd,MAAMC,EAAO,IAAId,EAAKE,GAElBa,EAAKV,EAALD,OACHW,EAAKR,EAALH,MAAWY,KAAOF,EAClBG,EAAKV,EAALH,KAAaU,KAEbG,EAAKZ,EAALD,KAAaU,GACbG,EAAKV,EAALH,KAAaU,IAGdG,EAAKT,EAALJ,MAAIS,EAAJE,EAAKP,EAALJ,QAAUS,GACX,CAEAK,OAAAA,GAAU,IAAAC,EACT,MAAMC,EAAUL,EAAKV,EAALD,MAChB,GAAKgB,EAML,OAFAH,EAAKZ,EAALD,KAAaW,EAAKV,EAALD,MAAWY,MACxBC,EAAKT,EAALJ,MAAIe,EAAJJ,EAAKP,EAALJ,QAAUe,IACHC,EAAQlB,KAChB,CAEAmB,IAAAA,GACC,GAAKN,EAAKV,EAALD,MAIL,OAAOW,EAAKV,EAALD,MAAWF,KAInB,CAEAS,KAAAA,GACCM,EAAKZ,EAALD,UAAakB,GACbL,EAAKV,EAALH,UAAakB,GACbL,EAAKT,EAALJ,KAAa,EACd,CAEA,QAAImB,GACH,OAAOR,EAAKP,EAALJ,KACR,CAEA,EAAGoB,OAAOC,YACT,IAAIL,EAAUL,EAAKV,EAALD,MAEd,KAAOgB,SACAA,EAAQlB,MACdkB,EAAUA,EAAQJ,IAEpB,EC1Ec,SAASU,EAAOC,GAC9BC,EAAoBD,GAEpB,MAAME,EAAQ,IAAIpB,EAClB,IAAIqB,EAAc,EAElB,MAAMC,EAAaA,KACdD,EAAcH,GAAeE,EAAMN,KAAO,IAC7CM,EAAMX,SAANW,GAEAC,IACD,EASKE,EAAMC,MAAOC,EAAWC,EAASC,KACtC,MAAMC,EAAS,UAAaH,KAAaE,GAA1B,GAEfD,EAAQE,GAER,UACOA,CACP,CAAE,MAAO,CAZTP,IAEAC,GAYM,EAyBDO,EAAY,SAACJ,GAAS,QAAAK,EAAAC,UAAAC,OAAKL,EAAU,IAAAM,MAAAH,EAAA,EAAAA,EAAA,KAAAI,EAAA,EAAAA,EAAAJ,EAAAI,IAAVP,EAAUO,EAAA,GAAAH,UAAAG,GAAA,OAAK,IAAIC,SAAQT,IAtB5CvB,EAACsB,EAAWC,EAASC,KAGpC,IAAIQ,SAAQC,IACXhB,EAAMjB,QAAQiC,EAAgB,IAC5BC,KACFd,EAAIe,UAAKzB,EAAWY,EAAWC,EAASC,IAGzC,iBAKOQ,QAAQT,UAEVL,EAAcH,GACjBI,GAED,EAVD,EAUI,EAIJnB,CAAQsB,EAAWC,EAASC,EAAW,GACtC,EA+BF,OA7BAY,OAAOC,iBAAiBX,EAAW,CAClCR,YAAa,CACZoB,IAAKA,IAAMpB,GAEZqB,aAAc,CACbD,IAAKA,IAAMrB,EAAMN,MAElB6B,WAAY,CACXlD,KAAAA,GACC2B,EAAMlB,OACP,GAEDgB,YAAa,CACZuB,IAAKA,IAAMvB,EAEX0B,GAAAA,CAAIC,GACH1B,EAAoB0B,GACpB3B,EAAc2B,EAEdC,gBAAe,KAEd,KAAOzB,EAAcH,GAAeE,EAAMN,KAAO,GAChDQ,GACD,GAEF,KAIKO,CACR,CASA,SAASV,EAAoBD,GAC5B,IAAO6B,OAAOC,UAAU9B,IAAgBA,IAAgB6B,OAAOE,qBAAsB/B,EAAc,GAClG,MAAM,IAAIgC,UAAU,sDAEtB,C,0BClCA,MAAAC,EAAA,CACAC,SAAA,CACAC,aAAAC,EAAAA,EAAAA,GAAA,kEACAC,MAAAC,EAAAA,EAAAA,IAAA,+BAEAC,SAAA,CACAJ,aAAAC,EAAAA,EAAAA,GAAA,4FACAC,MAAAC,EAAAA,EAAAA,IAAA,+BAEAE,KAAA,CACAL,aAAAC,EAAAA,EAAAA,GAAA,gFACAC,MAAAC,EAAAA,EAAAA,IAAA,4BAEAG,OAAA,CACAN,aAAAC,EAAAA,EAAAA,GAAA,8HACAC,MAAAC,EAAAA,EAAAA,IAAA,2BAEAI,cAAA,CACAC,KAAA,mBACAR,aAAAC,EAAAA,EAAAA,GAAA,8FACAC,MAAAC,EAAAA,EAAAA,IAAA,kCAEAM,MAAA,CACAT,aAAAC,EAAAA,EAAAA,GAAA,4CACAC,MAAAC,EAAAA,EAAAA,IAAA,0BAEAO,kBAAA,CACAC,QAAA,IAGAC,EAAA1B,OAAA2B,KAAAf,GCnG2L,EDqG3L,CACAU,KAAA,kBACAM,WAAA,CACAC,sBAAA,IACAC,SAAAA,EAAAA,GAEAC,KAAAA,KACA,CACAC,mBAAA,EACAC,gBAAA,EACAC,aAAA,EACAC,kBAAA,EACAC,KAAA,GACAC,gBAAAC,EAAAA,EAAAA,GAAA,2BAGAC,SAAA,CACAC,eAAAA,GACA,YAAAJ,KAAAK,QAAAC,GAAAhB,EAAAiB,SAAAD,EAAAE,KACA,EACAC,gBAAAA,GACA,YAAAL,gBAAAM,MAAAJ,GAAAA,EAAAK,YACA,GAEA,aAAAC,GACA,IACA,WAAAjB,SAAAkB,EAAAA,GAAA/C,KAAAgD,EAAAA,EAAAA,IAAA,uBACAC,EAAAC,KAAA,GAAArB,EAAAK,KAAA3C,uBAEA,KAAA2C,KAAAL,EAAAK,KAAAiB,KAAAX,GAAA1C,OAAAsD,OAAAZ,EAAA,CAAAa,SAAA,EAAAC,mBAAA,EAAAT,WAAAL,EAAAe,iBACAN,EAAAO,MAAA,QAAAlB,gBAAA/C,gCAAA,CAAA2C,KAAA,KAAAI,kBAEA,KAAAR,mBAAA,CACA,OAAA2B,GACAR,EAAAQ,MAAA,4BAAAA,UAEA,KAAAxB,kBAAA,CACA,SACA,KAAAD,aAAA,CACA,CACA,EACA0B,QAAA,CACAC,WAAAA,GACA,KAAA5B,gBAAA,EAEA,MAAA6B,EAAApF,EAAA,GACAqF,EAAA,KAAAvB,gBACAC,QAAAC,IAAAA,EAAAsB,QAAAtB,EAAAe,cAAAf,EAAAuB,YAAAvB,EAAAK,aACAM,KAAAX,GAAAoB,GAAA,UACAX,EAAAC,KAAA,cAAAV,EAAAE,MACAF,EAAAa,SAAA,EACAN,EAAAA,GAAAiB,MAAAhB,EAAAA,EAAAA,IAAA,yBAAAiB,OAAA,CAAAzB,EAAAE,IAAAwB,OAAA,KACAC,OAAAV,IACAR,EAAAQ,MAAA,qBAAAjB,EAAAE,KAAA,CAAAe,UACAjB,EAAAK,YAAA,EACAL,EAAAc,mBAAA,KAEA1D,MAAA,KACAqD,EAAAC,KAAA,aAAAV,EAAAE,MACAF,EAAAa,SAAA,EACAb,EAAAsB,QAAA,UAGAb,EAAAO,MAAA,cAAAK,EAAAtE,2BACAG,QAAA0E,IAAAP,GACAjE,MAAA,KACAqD,EAAAC,KAAA,iDAEAmB,OAAAC,SAAA,KAAAnC,cAAA,IAEAgC,OAAAV,GAAAR,EAAAQ,MAAA,sCAAAA,WACA,EACAc,WAAAC,GACAA,KAAA9D,GAAAA,EAAA8D,GAAA1D,KAIAJ,EAAA8D,GAAA1D,MAHAmC,EAAAwB,KAAA,mCAAAD,MACAzD,EAAAA,EAAAA,IAAA,uCAIA2D,WAAAlC,GACAA,EAAAE,MAAAhC,GAGAA,EAAA8B,EAAAE,IAAAtB,MAFAoB,EAAApB,KAIAuD,kBAAAH,GACAA,KAAA9D,EAIAA,EAAA8D,GAAA5D,aAHAqC,EAAAwB,KAAA,0CAAAD,KACA,IAIAI,SAAAJ,GACAA,KAAA9D,KAGAA,EAAA8D,GAAAjD,OAEAsD,YAAAA,CAAAL,GAEA,KAAAA,KAAA9D,KAAA,KAAAoB,kBACA,OAEA,MAAAgD,EAAA,KAAA5C,KAAA6C,WAAAvC,GAAAA,EAAAE,KAAA8B,IACA,KAAAQ,KAAA,KAAA9C,KAAA4C,GAAA,mBAAA5C,KAAA4C,GAAAjC,WACA,I,uIEnMIoC,EAAU,CAAC,EAEfA,EAAQC,kBAAoB,IAC5BD,EAAQE,cAAgB,IACxBF,EAAQG,OAAS,SAAc,KAAM,QACrCH,EAAQI,OAAS,IACjBJ,EAAQK,mBAAqB,IAEhB,IAAI,IAASL,GAKJ,KAAW,IAAQM,QAAS,IAAQA,OCL1D,SAXgB,E,SAAA,GACd,GNTW,WAAkB,IAAIC,EAAItI,KAAKuI,EAAGD,EAAIE,MAAMD,GAAG,OAAOA,EAAG,MAAM,CAACE,YAAY,YAAYC,MAAM,CAAC,iCAAiC,KAAK,CAACH,EAAG,KAAK,CAACD,EAAIK,GAAGL,EAAIM,GAAGN,EAAI3E,EAAE,OAAQ,wBAAwB2E,EAAIK,GAAG,KAAML,EAAIxD,YAAayD,EAAG,IAAI,CAACE,YAAY,uBAAuB,CAACH,EAAIK,GAAG,SAASL,EAAIM,GAAGN,EAAI3E,EAAE,OAAQ,mBAAmB,UAAW2E,EAAIvD,iBAAkBwD,EAAG,IAAI,CAACE,YAAY,6BAA6B,CAACH,EAAIK,GAAG,SAASL,EAAIM,GAAGN,EAAI3E,EAAE,OAAQ,qDAAqD,UAAU2E,EAAIO,KAAKP,EAAIK,GAAG,KAAKL,EAAIQ,GAAIR,EAAIlD,iBAAiB,SAASE,GAAK,OAAOiD,EAAG,MAAM,CAACQ,IAAIzD,EAAIE,GAAGiD,YAAY,OAAO,CAAGH,EAAIZ,SAASpC,EAAIE,IAAs0B8C,EAAIO,KAAr0B,CAACN,EAAG,MAAM,CAACG,MAAM,CAAC,IAAMJ,EAAIjB,WAAW/B,EAAIE,IAAI,IAAM,MAAM8C,EAAIK,GAAG,KAAKJ,EAAG,MAAM,CAACE,YAAY,QAAQ,CAACF,EAAG,KAAK,CAACD,EAAIK,GAAGL,EAAIM,GAAGN,EAAId,WAAWlC,OAASgD,EAAIK,GAAG,KAAKJ,EAAG,IAAI,CAACS,SAAS,CAAC,YAAcV,EAAIM,GAAGN,EAAIb,kBAAkBnC,EAAIE,QAAQ8C,EAAIK,GAAG,KAAMrD,EAAIc,kBAAmBmC,EAAG,IAAI,CAACA,EAAG,SAAS,CAACD,EAAIK,GAAGL,EAAIM,GAAGN,EAAI3E,EAAE,OAAQ,6CAA+C2B,EAAIe,aAA+Hf,EAAIuB,WAA8FyB,EAAIO,KAAtFN,EAAG,IAAI,CAACA,EAAG,SAAS,CAACD,EAAIK,GAAGL,EAAIM,GAAGN,EAAI3E,EAAE,OAAQ,iCAAlL4E,EAAG,IAAI,CAACA,EAAG,SAAS,CAACD,EAAIK,GAAGL,EAAIM,GAAGN,EAAI3E,EAAE,OAAQ,gEAA6K2E,EAAIK,GAAG,KAAKJ,EAAG,wBAAwB,CAACG,MAAM,CAAC,QAAUpD,EAAIK,YAAcL,EAAIsB,OAAO,UAAYtB,EAAIe,cAAgBf,EAAIsB,OAAO,QAAUtB,EAAIa,SAAS8C,GAAG,CAAC,iBAAiB,SAASC,GAAQ,OAAOZ,EAAIX,aAAarC,EAAIE,GAAG,OAAgB,EAAE,IAAG8C,EAAIK,GAAG,KAAKJ,EAAG,MAAM,CAACE,YAAY,cAAc,CAAEH,EAAI1D,oBAAsB0D,EAAIzD,eAAgB0D,EAAG,WAAW,CAACG,MAAM,CAAC,KAAO,WAAW,KAAO,OAAO,KAAOJ,EAAIrD,eAAe,sCAAsC,KAAK,CAACqD,EAAIK,GAAG,WAAWL,EAAIM,GAAGN,EAAI3E,EAAE,OAAQ,SAAS,YAAY2E,EAAIO,KAAKP,EAAIK,GAAG,KAAML,EAAI1D,kBAAmB2D,EAAG,WAAW,CAACG,MAAM,CAAC,KAAO,UAAU,SAAWJ,EAAIzD,iBAAmByD,EAAI7C,iBAAiB,yCAAyC,KAAK,CAAC6C,EAAIK,GAAG,qDAAuDL,EAAIM,GAAGN,EAAIzD,eAAiByD,EAAI3E,EAAE,OAAQ,qBAAuB2E,EAAI3E,EAAE,OAAQ,6BAA6B,YAAY2E,EAAIO,MAAM,IAAI,EACvnE,GACsB,IMUpB,EACA,KACA,WACA,MAI8B,QCNhCM,EAAAA,IAAoBC,EAAAA,EAAAA,MAEpBC,EAAAA,GAAIC,MAAM,CACT9C,QAAS,CACR7C,EAACA,EAAAA,OAKH,IADa0F,EAAAA,GAAIE,OAAOC,KACbC,OAAO,qBAElB1D,EAAOO,MAAM,iC,sECrBToD,E,MAA0B,GAA4B,KAE1DA,EAAwBC,KAAK,CAACC,EAAOpE,GAAI,upBAAwpB,GAAG,CAAC,QAAU,EAAE,QAAU,CAAC,6DAA6D,MAAQ,GAAG,SAAW,oOAAoO,eAAiB,CAAC,goBAAgoB,WAAa,MAElrD,S,GCNIqE,EAA2B,CAAC,EAGhC,SAASC,EAAoBC,GAE5B,IAAIC,EAAeH,EAAyBE,GAC5C,QAAqB7I,IAAjB8I,EACH,OAAOA,EAAaC,QAGrB,IAAIL,EAASC,EAAyBE,GAAY,CACjDvE,GAAIuE,EACJG,QAAQ,EACRD,QAAS,CAAC,GAUX,OANAE,EAAoBJ,GAAUK,KAAKR,EAAOK,QAASL,EAAQA,EAAOK,QAASH,GAG3EF,EAAOM,QAAS,EAGTN,EAAOK,OACf,CAGAH,EAAoBO,EAAIF,EX5BpBhL,EAAW,GACf2K,EAAoBQ,EAAI,CAACrI,EAAQsI,EAAUC,EAAIC,KAC9C,IAAGF,EAAH,CAMA,IAAIG,EAAeC,IACnB,IAASC,EAAI,EAAGA,EAAIzL,EAASkD,OAAQuI,IAAK,CACrCL,EAAWpL,EAASyL,GAAG,GACvBJ,EAAKrL,EAASyL,GAAG,GACjBH,EAAWtL,EAASyL,GAAG,GAE3B,IAJA,IAGIC,GAAY,EACPC,EAAI,EAAGA,EAAIP,EAASlI,OAAQyI,MACpB,EAAXL,GAAsBC,GAAgBD,IAAa7H,OAAO2B,KAAKuF,EAAoBQ,GAAGS,OAAOhC,GAASe,EAAoBQ,EAAEvB,GAAKwB,EAASO,MAC9IP,EAASS,OAAOF,IAAK,IAErBD,GAAY,EACTJ,EAAWC,IAAcA,EAAeD,IAG7C,GAAGI,EAAW,CACb1L,EAAS6L,OAAOJ,IAAK,GACrB,IAAIK,EAAIT,SACEtJ,IAAN+J,IAAiBhJ,EAASgJ,EAC/B,CACD,CACA,OAAOhJ,CArBP,CAJCwI,EAAWA,GAAY,EACvB,IAAI,IAAIG,EAAIzL,EAASkD,OAAQuI,EAAI,GAAKzL,EAASyL,EAAI,GAAG,GAAKH,EAAUG,IAAKzL,EAASyL,GAAKzL,EAASyL,EAAI,GACrGzL,EAASyL,GAAK,CAACL,EAAUC,EAAIC,EAuBjB,EY3BdX,EAAoBoB,EAAKtB,IACxB,IAAIuB,EAASvB,GAAUA,EAAOwB,WAC7B,IAAOxB,EAAiB,QACxB,IAAM,EAEP,OADAE,EAAoBuB,EAAEF,EAAQ,CAAEG,EAAGH,IAC5BA,CAAM,ECLdrB,EAAoBuB,EAAI,CAACpB,EAASsB,KACjC,IAAI,IAAIxC,KAAOwC,EACXzB,EAAoB0B,EAAED,EAAYxC,KAASe,EAAoB0B,EAAEvB,EAASlB,IAC5EnG,OAAO6I,eAAexB,EAASlB,EAAK,CAAE2C,YAAY,EAAM5I,IAAKyI,EAAWxC,IAE1E,ECHDe,EAAoB6B,EAAI,IAAOnJ,QAAQT,UCHvC+H,EAAoB8B,EAAI,WACvB,GAA0B,iBAAfC,WAAyB,OAAOA,WAC3C,IACC,OAAO7L,MAAQ,IAAI8L,SAAS,cAAb,EAChB,CAAE,MAAOH,GACR,GAAsB,iBAAXxE,OAAqB,OAAOA,MACxC,CACA,CAPuB,GCAxB2C,EAAoB0B,EAAI,CAACO,EAAKC,IAAUpJ,OAAOqJ,UAAUC,eAAe9B,KAAK2B,EAAKC,GCClFlC,EAAoBmB,EAAKhB,IACH,oBAAX7I,QAA0BA,OAAO+K,aAC1CvJ,OAAO6I,eAAexB,EAAS7I,OAAO+K,YAAa,CAAErM,MAAO,WAE7D8C,OAAO6I,eAAexB,EAAS,aAAc,CAAEnK,OAAO,GAAO,ECL9DgK,EAAoBsC,IAAOxC,IAC1BA,EAAOyC,MAAQ,GACVzC,EAAO0C,WAAU1C,EAAO0C,SAAW,IACjC1C,GCHRE,EAAoBgB,EAAI,K,MCAxBhB,EAAoByC,EAAIC,SAASC,SAAWC,KAAKtF,SAASuF,KAK1D,IAAIC,EAAkB,CACrB,KAAM,GAaP9C,EAAoBQ,EAAEQ,EAAK+B,GAA0C,IAA7BD,EAAgBC,GAGxD,IAAIC,EAAuB,CAACC,EAA4BpI,KACvD,IAKIoF,EAAU8C,EALVtC,EAAW5F,EAAK,GAChBqI,EAAcrI,EAAK,GACnBsI,EAAUtI,EAAK,GAGIiG,EAAI,EAC3B,GAAGL,EAAS7E,MAAMF,GAAgC,IAAxBoH,EAAgBpH,KAAa,CACtD,IAAIuE,KAAYiD,EACZlD,EAAoB0B,EAAEwB,EAAajD,KACrCD,EAAoBO,EAAEN,GAAYiD,EAAYjD,IAGhD,GAAGkD,EAAS,IAAIhL,EAASgL,EAAQnD,EAClC,CAEA,IADGiD,GAA4BA,EAA2BpI,GACrDiG,EAAIL,EAASlI,OAAQuI,IACzBiC,EAAUtC,EAASK,GAChBd,EAAoB0B,EAAEoB,EAAiBC,IAAYD,EAAgBC,IACrED,EAAgBC,GAAS,KAE1BD,EAAgBC,GAAW,EAE5B,OAAO/C,EAAoBQ,EAAErI,EAAO,EAGjCiL,EAAqBR,KAA4B,sBAAIA,KAA4B,uBAAK,GAC1FQ,EAAmBC,QAAQL,EAAqBnK,KAAK,KAAM,IAC3DuK,EAAmBvD,KAAOmD,EAAqBnK,KAAK,KAAMuK,EAAmBvD,KAAKhH,KAAKuK,G,KClDvFpD,EAAoBsD,QAAKlM,ECGzB,IAAImM,EAAsBvD,EAAoBQ,OAAEpJ,EAAW,CAAC,OAAO,IAAO4I,EAAoB,SAC9FuD,EAAsBvD,EAAoBQ,EAAE+C,E","sources":["webpack:///nextcloud/webpack/runtime/chunk loaded","webpack:///nextcloud/core/src/logger.js","webpack://nextcloud/./core/src/components/setup/RecommendedApps.vue?5f06","webpack:///nextcloud/node_modules/yocto-queue/index.js","webpack:///nextcloud/node_modules/p-limit/index.js","webpack:///nextcloud/core/src/components/setup/RecommendedApps.vue","webpack:///nextcloud/core/src/components/setup/RecommendedApps.vue?vue&type=script&lang=js","webpack://nextcloud/./core/src/components/setup/RecommendedApps.vue?304a","webpack://nextcloud/./core/src/components/setup/RecommendedApps.vue?84e8","webpack:///nextcloud/core/src/recommendedapps.js","webpack:///nextcloud/core/src/components/setup/RecommendedApps.vue?vue&type=style&index=0&id=5b5c8ecc&prod&lang=scss&scoped=true","webpack:///nextcloud/webpack/bootstrap","webpack:///nextcloud/webpack/runtime/compat get default export","webpack:///nextcloud/webpack/runtime/define property getters","webpack:///nextcloud/webpack/runtime/ensure chunk","webpack:///nextcloud/webpack/runtime/global","webpack:///nextcloud/webpack/runtime/hasOwnProperty shorthand","webpack:///nextcloud/webpack/runtime/make namespace object","webpack:///nextcloud/webpack/runtime/node module decorator","webpack:///nextcloud/webpack/runtime/runtimeId","webpack:///nextcloud/webpack/runtime/jsonp chunk loading","webpack:///nextcloud/webpack/runtime/nonce","webpack:///nextcloud/webpack/startup"],"sourcesContent":["var deferred = [];\n__webpack_require__.O = (result, chunkIds, fn, priority) => {\n\tif(chunkIds) {\n\t\tpriority = priority || 0;\n\t\tfor(var i = deferred.length; i > 0 && deferred[i - 1][2] > priority; i--) deferred[i] = deferred[i - 1];\n\t\tdeferred[i] = [chunkIds, fn, priority];\n\t\treturn;\n\t}\n\tvar notFulfilled = Infinity;\n\tfor (var i = 0; i < deferred.length; i++) {\n\t\tvar chunkIds = deferred[i][0];\n\t\tvar fn = deferred[i][1];\n\t\tvar priority = deferred[i][2];\n\t\tvar fulfilled = true;\n\t\tfor (var j = 0; j < chunkIds.length; j++) {\n\t\t\tif ((priority & 1 === 0 || notFulfilled >= priority) && Object.keys(__webpack_require__.O).every((key) => (__webpack_require__.O[key](chunkIds[j])))) {\n\t\t\t\tchunkIds.splice(j--, 1);\n\t\t\t} else {\n\t\t\t\tfulfilled = false;\n\t\t\t\tif(priority < notFulfilled) notFulfilled = priority;\n\t\t\t}\n\t\t}\n\t\tif(fulfilled) {\n\t\t\tdeferred.splice(i--, 1)\n\t\t\tvar r = fn();\n\t\t\tif (r !== undefined) result = r;\n\t\t}\n\t}\n\treturn result;\n};","/**\n * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getCurrentUser } from '@nextcloud/auth'\nimport { getLoggerBuilder } from '@nextcloud/logger'\n\nconst getLogger = user => {\n\tif (user === null) {\n\t\treturn getLoggerBuilder()\n\t\t\t.setApp('core')\n\t\t\t.build()\n\t}\n\treturn getLoggerBuilder()\n\t\t.setApp('core')\n\t\t.setUid(user.uid)\n\t\t.build()\n}\n\nexport default getLogger(getCurrentUser())\n\nexport const unifiedSearchLogger = getLoggerBuilder()\n\t.setApp('unified-search')\n\t.detectUser()\n\t.build()\n","var render = function render(){var _vm=this,_c=_vm._self._c;return _c('div',{staticClass:\"guest-box\",attrs:{\"data-cy-setup-recommended-apps\":\"\"}},[_c('h2',[_vm._v(_vm._s(_vm.t('core', 'Recommended apps')))]),_vm._v(\" \"),(_vm.loadingApps)?_c('p',{staticClass:\"loading text-center\"},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('core', 'Loading apps …'))+\"\\n\\t\")]):(_vm.loadingAppsError)?_c('p',{staticClass:\"loading-error text-center\"},[_vm._v(\"\\n\\t\\t\"+_vm._s(_vm.t('core', 'Could not fetch list of apps from the App Store.'))+\"\\n\\t\")]):_vm._e(),_vm._v(\" \"),_vm._l((_vm.recommendedApps),function(app){return _c('div',{key:app.id,staticClass:\"app\"},[(!_vm.isHidden(app.id))?[_c('img',{attrs:{\"src\":_vm.customIcon(app.id),\"alt\":\"\"}}),_vm._v(\" \"),_c('div',{staticClass:\"info\"},[_c('h3',[_vm._v(_vm._s(_vm.customName(app)))]),_vm._v(\" \"),_c('p',{domProps:{\"textContent\":_vm._s(_vm.customDescription(app.id))}}),_vm._v(\" \"),(app.installationError)?_c('p',[_c('strong',[_vm._v(_vm._s(_vm.t('core', 'App download or installation failed')))])]):(!app.isCompatible)?_c('p',[_c('strong',[_vm._v(_vm._s(_vm.t('core', 'Cannot install this app because it is not compatible')))])]):(!app.canInstall)?_c('p',[_c('strong',[_vm._v(_vm._s(_vm.t('core', 'Cannot install this app')))])]):_vm._e()]),_vm._v(\" \"),_c('NcCheckboxRadioSwitch',{attrs:{\"checked\":app.isSelected || app.active,\"disabled\":!app.isCompatible || app.active,\"loading\":app.loading},on:{\"update:checked\":function($event){return _vm.toggleSelect(app.id)}}})]:_vm._e()],2)}),_vm._v(\" \"),_c('div',{staticClass:\"dialog-row\"},[(_vm.showInstallButton && !_vm.installingApps)?_c('NcButton',{attrs:{\"type\":\"tertiary\",\"role\":\"link\",\"href\":_vm.defaultPageUrl,\"data-cy-setup-recommended-apps-skip\":\"\"}},[_vm._v(\"\\n\\t\\t\\t\"+_vm._s(_vm.t('core', 'Skip'))+\"\\n\\t\\t\")]):_vm._e(),_vm._v(\" \"),(_vm.showInstallButton)?_c('NcButton',{attrs:{\"type\":\"primary\",\"disabled\":_vm.installingApps || !_vm.isAnyAppSelected,\"data-cy-setup-recommended-apps-install\":\"\"}},[_vm._v(\"\\n\\t\\t\\t@click.stop.prevent=\\\"installApps\\\">\\n\\t\\t\\t\"+_vm._s(_vm.installingApps ? _vm.t('core', 'Installing apps …') : _vm.t('core', 'Install recommended apps'))+\"\\n\\t\\t\")]):_vm._e()],1)],2)\n}\nvar staticRenderFns = []\n\nexport { render, staticRenderFns }","/*\nHow it works:\n`this.#head` is an instance of `Node` which keeps track of its current value and nests another instance of `Node` that keeps the value that comes after it. When a value is provided to `.enqueue()`, the code needs to iterate through `this.#head`, going deeper and deeper to find the last value. However, iterating through every single item is slow. This problem is solved by saving a reference to the last value as `this.#tail` so that it can reference it to add a new value.\n*/\n\nclass Node {\n\tvalue;\n\tnext;\n\n\tconstructor(value) {\n\t\tthis.value = value;\n\t}\n}\n\nexport default class Queue {\n\t#head;\n\t#tail;\n\t#size;\n\n\tconstructor() {\n\t\tthis.clear();\n\t}\n\n\tenqueue(value) {\n\t\tconst node = new Node(value);\n\n\t\tif (this.#head) {\n\t\t\tthis.#tail.next = node;\n\t\t\tthis.#tail = node;\n\t\t} else {\n\t\t\tthis.#head = node;\n\t\t\tthis.#tail = node;\n\t\t}\n\n\t\tthis.#size++;\n\t}\n\n\tdequeue() {\n\t\tconst current = this.#head;\n\t\tif (!current) {\n\t\t\treturn;\n\t\t}\n\n\t\tthis.#head = this.#head.next;\n\t\tthis.#size--;\n\t\treturn current.value;\n\t}\n\n\tpeek() {\n\t\tif (!this.#head) {\n\t\t\treturn;\n\t\t}\n\n\t\treturn this.#head.value;\n\n\t\t// TODO: Node.js 18.\n\t\t// return this.#head?.value;\n\t}\n\n\tclear() {\n\t\tthis.#head = undefined;\n\t\tthis.#tail = undefined;\n\t\tthis.#size = 0;\n\t}\n\n\tget size() {\n\t\treturn this.#size;\n\t}\n\n\t* [Symbol.iterator]() {\n\t\tlet current = this.#head;\n\n\t\twhile (current) {\n\t\t\tyield current.value;\n\t\t\tcurrent = current.next;\n\t\t}\n\t}\n}\n","import Queue from 'yocto-queue';\n\nexport default function pLimit(concurrency) {\n\tvalidateConcurrency(concurrency);\n\n\tconst queue = new Queue();\n\tlet activeCount = 0;\n\n\tconst resumeNext = () => {\n\t\tif (activeCount < concurrency && queue.size > 0) {\n\t\t\tqueue.dequeue()();\n\t\t\t// Since `pendingCount` has been decreased by one, increase `activeCount` by one.\n\t\t\tactiveCount++;\n\t\t}\n\t};\n\n\tconst next = () => {\n\t\tactiveCount--;\n\n\t\tresumeNext();\n\t};\n\n\tconst run = async (function_, resolve, arguments_) => {\n\t\tconst result = (async () => function_(...arguments_))();\n\n\t\tresolve(result);\n\n\t\ttry {\n\t\t\tawait result;\n\t\t} catch {}\n\n\t\tnext();\n\t};\n\n\tconst enqueue = (function_, resolve, arguments_) => {\n\t\t// Queue `internalResolve` instead of the `run` function\n\t\t// to preserve asynchronous context.\n\t\tnew Promise(internalResolve => {\n\t\t\tqueue.enqueue(internalResolve);\n\t\t}).then(\n\t\t\trun.bind(undefined, function_, resolve, arguments_),\n\t\t);\n\n\t\t(async () => {\n\t\t\t// This function needs to wait until the next microtask before comparing\n\t\t\t// `activeCount` to `concurrency`, because `activeCount` is updated asynchronously\n\t\t\t// after the `internalResolve` function is dequeued and called. The comparison in the if-statement\n\t\t\t// needs to happen asynchronously as well to get an up-to-date value for `activeCount`.\n\t\t\tawait Promise.resolve();\n\n\t\t\tif (activeCount < concurrency) {\n\t\t\t\tresumeNext();\n\t\t\t}\n\t\t})();\n\t};\n\n\tconst generator = (function_, ...arguments_) => new Promise(resolve => {\n\t\tenqueue(function_, resolve, arguments_);\n\t});\n\n\tObject.defineProperties(generator, {\n\t\tactiveCount: {\n\t\t\tget: () => activeCount,\n\t\t},\n\t\tpendingCount: {\n\t\t\tget: () => queue.size,\n\t\t},\n\t\tclearQueue: {\n\t\t\tvalue() {\n\t\t\t\tqueue.clear();\n\t\t\t},\n\t\t},\n\t\tconcurrency: {\n\t\t\tget: () => concurrency,\n\n\t\t\tset(newConcurrency) {\n\t\t\t\tvalidateConcurrency(newConcurrency);\n\t\t\t\tconcurrency = newConcurrency;\n\n\t\t\t\tqueueMicrotask(() => {\n\t\t\t\t\t// eslint-disable-next-line no-unmodified-loop-condition\n\t\t\t\t\twhile (activeCount < concurrency && queue.size > 0) {\n\t\t\t\t\t\tresumeNext();\n\t\t\t\t\t}\n\t\t\t\t});\n\t\t\t},\n\t\t},\n\t});\n\n\treturn generator;\n}\n\nexport function limitFunction(function_, option) {\n\tconst {concurrency} = option;\n\tconst limit = pLimit(concurrency);\n\n\treturn (...arguments_) => limit(() => function_(...arguments_));\n}\n\nfunction validateConcurrency(concurrency) {\n\tif (!((Number.isInteger(concurrency) || concurrency === Number.POSITIVE_INFINITY) && concurrency > 0)) {\n\t\tthrow new TypeError('Expected `concurrency` to be a number from 1 and up');\n\t}\n}\n","<!--\n - SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n - SPDX-License-Identifier: AGPL-3.0-or-later\n-->\n\n<template>\n\t<div class=\"guest-box\" data-cy-setup-recommended-apps>\n\t\t<h2>{{ t('core', 'Recommended apps') }}</h2>\n\t\t<p v-if=\"loadingApps\" class=\"loading text-center\">\n\t\t\t{{ t('core', 'Loading apps …') }}\n\t\t</p>\n\t\t<p v-else-if=\"loadingAppsError\" class=\"loading-error text-center\">\n\t\t\t{{ t('core', 'Could not fetch list of apps from the App Store.') }}\n\t\t</p>\n\n\t\t<div v-for=\"app in recommendedApps\" :key=\"app.id\" class=\"app\">\n\t\t\t<template v-if=\"!isHidden(app.id)\">\n\t\t\t\t<img :src=\"customIcon(app.id)\" alt=\"\">\n\t\t\t\t<div class=\"info\">\n\t\t\t\t\t<h3>{{ customName(app) }}</h3>\n\t\t\t\t\t<p v-text=\"customDescription(app.id)\" />\n\t\t\t\t\t<p v-if=\"app.installationError\">\n\t\t\t\t\t\t<strong>{{ t('core', 'App download or installation failed') }}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t\t<p v-else-if=\"!app.isCompatible\">\n\t\t\t\t\t\t<strong>{{ t('core', 'Cannot install this app because it is not compatible') }}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t\t<p v-else-if=\"!app.canInstall\">\n\t\t\t\t\t\t<strong>{{ t('core', 'Cannot install this app') }}</strong>\n\t\t\t\t\t</p>\n\t\t\t\t</div>\n\t\t\t\t<NcCheckboxRadioSwitch :checked=\"app.isSelected || app.active\"\n\t\t\t\t\t:disabled=\"!app.isCompatible || app.active\"\n\t\t\t\t\t:loading=\"app.loading\"\n\t\t\t\t\t@update:checked=\"toggleSelect(app.id)\" />\n\t\t\t</template>\n\t\t</div>\n\n\t\t<div class=\"dialog-row\">\n\t\t\t<NcButton v-if=\"showInstallButton && !installingApps\"\n\t\t\t\ttype=\"tertiary\"\n\t\t\t\trole=\"link\"\n\t\t\t\t:href=\"defaultPageUrl\"\n\t\t\t\tdata-cy-setup-recommended-apps-skip>\n\t\t\t\t{{ t('core', 'Skip') }}\n\t\t\t</NcButton>\n\n\t\t\t<NcButton v-if=\"showInstallButton\"\n\t\t\t\ttype=\"primary\"\n\t\t\t\t:disabled=\"installingApps || !isAnyAppSelected\"\n\t\t\t\tdata-cy-setup-recommended-apps-install>\n\t\t\t\t@click.stop.prevent=\"installApps\">\n\t\t\t\t{{ installingApps ? t('core', 'Installing apps …') : t('core', 'Install recommended apps') }}\n\t\t\t</NcButton>\n\t\t</div>\n\t</div>\n</template>\n\n<script>\nimport { t } from '@nextcloud/l10n'\nimport { loadState } from '@nextcloud/initial-state'\nimport { generateUrl, imagePath } from '@nextcloud/router'\nimport axios from '@nextcloud/axios'\nimport pLimit from 'p-limit'\nimport logger from '../../logger.js'\n\nimport NcButton from '@nextcloud/vue/components/NcButton'\nimport NcCheckboxRadioSwitch from '@nextcloud/vue/components/NcCheckboxRadioSwitch'\n\nconst recommended = {\n\tcalendar: {\n\t\tdescription: t('core', 'Schedule work & meetings, synced with all your devices.'),\n\t\ticon: imagePath('core', 'places/calendar.svg'),\n\t},\n\tcontacts: {\n\t\tdescription: t('core', 'Keep your colleagues and friends in one place without leaking their private info.'),\n\t\ticon: imagePath('core', 'places/contacts.svg'),\n\t},\n\tmail: {\n\t\tdescription: t('core', 'Simple email app nicely integrated with Files, Contacts and Calendar.'),\n\t\ticon: imagePath('core', 'actions/mail.svg'),\n\t},\n\tspreed: {\n\t\tdescription: t('core', 'Chatting, video calls, screen sharing, online meetings and web conferencing – in your browser and with mobile apps.'),\n\t\ticon: imagePath('core', 'apps/spreed.svg'),\n\t},\n\trichdocuments: {\n\t\tname: 'Nextcloud Office',\n\t\tdescription: t('core', 'Collaborative documents, spreadsheets and presentations, built on Collabora Online.'),\n\t\ticon: imagePath('core', 'apps/richdocuments.svg'),\n\t},\n\tnotes: {\n\t\tdescription: t('core', 'Distraction free note taking app.'),\n\t\ticon: imagePath('core', 'apps/notes.svg'),\n\t},\n\trichdocumentscode: {\n\t\thidden: true,\n\t},\n}\nconst recommendedIds = Object.keys(recommended)\n\nexport default {\n\tname: 'RecommendedApps',\n\tcomponents: {\n\t\tNcCheckboxRadioSwitch,\n\t\tNcButton,\n\t},\n\tdata() {\n\t\treturn {\n\t\t\tshowInstallButton: false,\n\t\t\tinstallingApps: false,\n\t\t\tloadingApps: true,\n\t\t\tloadingAppsError: false,\n\t\t\tapps: [],\n\t\t\tdefaultPageUrl: loadState('core', 'defaultPageUrl'),\n\t\t}\n\t},\n\tcomputed: {\n\t\trecommendedApps() {\n\t\t\treturn this.apps.filter(app => recommendedIds.includes(app.id))\n\t\t},\n\t\tisAnyAppSelected() {\n\t\t\treturn this.recommendedApps.some(app => app.isSelected)\n\t\t},\n\t},\n\tasync mounted() {\n\t\ttry {\n\t\t\tconst { data } = await axios.get(generateUrl('settings/apps/list'))\n\t\t\tlogger.info(`${data.apps.length} apps fetched`)\n\n\t\t\tthis.apps = data.apps.map(app => Object.assign(app, { loading: false, installationError: false, isSelected: app.isCompatible }))\n\t\t\tlogger.debug(`${this.recommendedApps.length} recommended apps found`, { apps: this.recommendedApps })\n\n\t\t\tthis.showInstallButton = true\n\t\t} catch (error) {\n\t\t\tlogger.error('could not fetch app list', { error })\n\n\t\t\tthis.loadingAppsError = true\n\t\t} finally {\n\t\t\tthis.loadingApps = false\n\t\t}\n\t},\n\tmethods: {\n\t\tinstallApps() {\n\t\t\tthis.installingApps = true\n\n\t\t\tconst limit = pLimit(1)\n\t\t\tconst installing = this.recommendedApps\n\t\t\t\t.filter(app => !app.active && app.isCompatible && app.canInstall && app.isSelected)\n\t\t\t\t.map(app => limit(async () => {\n\t\t\t\t\tlogger.info(`installing ${app.id}`)\n\t\t\t\t\tapp.loading = true\n\t\t\t\t\treturn axios.post(generateUrl('settings/apps/enable'), { appIds: [app.id], groups: [] })\n\t\t\t\t\t\t.catch(error => {\n\t\t\t\t\t\t\tlogger.error(`could not install ${app.id}`, { error })\n\t\t\t\t\t\t\tapp.isSelected = false\n\t\t\t\t\t\t\tapp.installationError = true\n\t\t\t\t\t\t})\n\t\t\t\t\t\t.then(() => {\n\t\t\t\t\t\t\tlogger.info(`installed ${app.id}`)\n\t\t\t\t\t\t\tapp.loading = false\n\t\t\t\t\t\t\tapp.active = true\n\t\t\t\t\t\t})\n\t\t\t\t}))\n\t\t\tlogger.debug(`installing ${installing.length} recommended apps`)\n\t\t\tPromise.all(installing)\n\t\t\t\t.then(() => {\n\t\t\t\t\tlogger.info('all recommended apps installed, redirecting …')\n\n\t\t\t\t\twindow.location = this.defaultPageUrl\n\t\t\t\t})\n\t\t\t\t.catch(error => logger.error('could not install recommended apps', { error }))\n\t\t},\n\t\tcustomIcon(appId) {\n\t\t\tif (!(appId in recommended) || !recommended[appId].icon) {\n\t\t\t\tlogger.warn(`no app icon for recommended app ${appId}`)\n\t\t\t\treturn imagePath('core', 'places/default-app-icon.svg')\n\t\t\t}\n\t\t\treturn recommended[appId].icon\n\t\t},\n\t\tcustomName(app) {\n\t\t\tif (!(app.id in recommended)) {\n\t\t\t\treturn app.name\n\t\t\t}\n\t\t\treturn recommended[app.id].name || app.name\n\t\t},\n\t\tcustomDescription(appId) {\n\t\t\tif (!(appId in recommended)) {\n\t\t\t\tlogger.warn(`no app description for recommended app ${appId}`)\n\t\t\t\treturn ''\n\t\t\t}\n\t\t\treturn recommended[appId].description\n\t\t},\n\t\tisHidden(appId) {\n\t\t\tif (!(appId in recommended)) {\n\t\t\t\treturn false\n\t\t\t}\n\t\t\treturn !!recommended[appId].hidden\n\t\t},\n\t\ttoggleSelect(appId) {\n\t\t\t// disable toggle when installButton is disabled\n\t\t\tif (!(appId in recommended) || !this.showInstallButton) {\n\t\t\t\treturn\n\t\t\t}\n\t\t\tconst index = this.apps.findIndex(app => app.id === appId)\n\t\t\tthis.$set(this.apps[index], 'isSelected', !this.apps[index].isSelected)\n\t\t},\n\t},\n}\n</script>\n\n<style lang=\"scss\" scoped>\n.dialog-row {\n\tdisplay: flex;\n\tjustify-content: end;\n\tmargin-top: 8px;\n}\n\np {\n\t&.loading,\n\t&.loading-error {\n\t\theight: 100px;\n\t}\n\n\t&:last-child {\n\t\tmargin-top: 10px;\n\t}\n}\n\n.text-center {\n\ttext-align: center;\n}\n\n.app {\n\tdisplay: flex;\n\tflex-direction: row;\n\n\timg {\n\t\theight: 50px;\n\t\twidth: 50px;\n\t\tfilter: var(--background-invert-if-dark);\n\t}\n\n\timg, .info {\n\t\tpadding: 12px;\n\t}\n\n\t.info {\n\t\th3, p {\n\t\t\ttext-align: start;\n\t\t}\n\n\t\th3 {\n\t\t\tmargin-top: 0;\n\t\t}\n\t}\n\n\t.checkbox-radio-switch {\n\t\tmargin-inline-start: auto;\n\t\tpadding: 0 2px;\n\t}\n}\n</style>\n","import mod from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=script&lang=js\"; export default mod; export * from \"-!../../../../node_modules/babel-loader/lib/index.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=script&lang=js\"","\n import API from \"!../../../../node_modules/style-loader/dist/runtime/injectStylesIntoStyleTag.js\";\n import domAPI from \"!../../../../node_modules/style-loader/dist/runtime/styleDomAPI.js\";\n import insertFn from \"!../../../../node_modules/style-loader/dist/runtime/insertBySelector.js\";\n import setAttributes from \"!../../../../node_modules/style-loader/dist/runtime/setAttributesWithoutAttributes.js\";\n import insertStyleElement from \"!../../../../node_modules/style-loader/dist/runtime/insertStyleElement.js\";\n import styleTagTransformFn from \"!../../../../node_modules/style-loader/dist/runtime/styleTagTransform.js\";\n import content, * as namedExport from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=style&index=0&id=5b5c8ecc&prod&lang=scss&scoped=true\";\n \n \n\nvar options = {};\n\noptions.styleTagTransform = styleTagTransformFn;\noptions.setAttributes = setAttributes;\noptions.insert = insertFn.bind(null, \"head\");\noptions.domAPI = domAPI;\noptions.insertStyleElement = insertStyleElement;\n\nvar update = API(content, options);\n\n\n\nexport * from \"!!../../../../node_modules/css-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/loaders/stylePostLoader.js!../../../../node_modules/sass-loader/dist/cjs.js!../../../../node_modules/vue-loader/lib/index.js??vue-loader-options!./RecommendedApps.vue?vue&type=style&index=0&id=5b5c8ecc&prod&lang=scss&scoped=true\";\n export default content && content.locals ? content.locals : undefined;\n","import { render, staticRenderFns } from \"./RecommendedApps.vue?vue&type=template&id=5b5c8ecc&scoped=true\"\nimport script from \"./RecommendedApps.vue?vue&type=script&lang=js\"\nexport * from \"./RecommendedApps.vue?vue&type=script&lang=js\"\nimport style0 from \"./RecommendedApps.vue?vue&type=style&index=0&id=5b5c8ecc&prod&lang=scss&scoped=true\"\n\n\n/* normalize component */\nimport normalizer from \"!../../../../node_modules/vue-loader/lib/runtime/componentNormalizer.js\"\nvar component = normalizer(\n script,\n render,\n staticRenderFns,\n false,\n null,\n \"5b5c8ecc\",\n null\n \n)\n\nexport default component.exports","/**\n * SPDX-FileCopyrightText: 2019 Nextcloud GmbH and Nextcloud contributors\n * SPDX-License-Identifier: AGPL-3.0-or-later\n */\n\nimport { getCSPNonce } from '@nextcloud/auth'\nimport { translate as t } from '@nextcloud/l10n'\nimport Vue from 'vue'\n\nimport logger from './logger.js'\nimport RecommendedApps from './components/setup/RecommendedApps.vue'\n\n// eslint-disable-next-line camelcase\n__webpack_nonce__ = getCSPNonce()\n\nVue.mixin({\n\tmethods: {\n\t\tt,\n\t},\n})\n\nconst View = Vue.extend(RecommendedApps)\nnew View().$mount('#recommended-apps')\n\nlogger.debug('recommended apps view rendered')\n","// Imports\nimport ___CSS_LOADER_API_SOURCEMAP_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/sourceMaps.js\";\nimport ___CSS_LOADER_API_IMPORT___ from \"../../../../node_modules/css-loader/dist/runtime/api.js\";\nvar ___CSS_LOADER_EXPORT___ = ___CSS_LOADER_API_IMPORT___(___CSS_LOADER_API_SOURCEMAP_IMPORT___);\n// Module\n___CSS_LOADER_EXPORT___.push([module.id, `.dialog-row[data-v-5b5c8ecc]{display:flex;justify-content:end;margin-top:8px}p.loading[data-v-5b5c8ecc],p.loading-error[data-v-5b5c8ecc]{height:100px}p[data-v-5b5c8ecc]:last-child{margin-top:10px}.text-center[data-v-5b5c8ecc]{text-align:center}.app[data-v-5b5c8ecc]{display:flex;flex-direction:row}.app img[data-v-5b5c8ecc]{height:50px;width:50px;filter:var(--background-invert-if-dark)}.app img[data-v-5b5c8ecc],.app .info[data-v-5b5c8ecc]{padding:12px}.app .info h3[data-v-5b5c8ecc],.app .info p[data-v-5b5c8ecc]{text-align:start}.app .info h3[data-v-5b5c8ecc]{margin-top:0}.app .checkbox-radio-switch[data-v-5b5c8ecc]{margin-inline-start:auto;padding:0 2px}`, \"\",{\"version\":3,\"sources\":[\"webpack://./core/src/components/setup/RecommendedApps.vue\"],\"names\":[],\"mappings\":\"AACA,6BACC,YAAA,CACA,mBAAA,CACA,cAAA,CAIA,4DAEC,YAAA,CAGD,8BACC,eAAA,CAIF,8BACC,iBAAA,CAGD,sBACC,YAAA,CACA,kBAAA,CAEA,0BACC,WAAA,CACA,UAAA,CACA,uCAAA,CAGD,sDACC,YAAA,CAIA,6DACC,gBAAA,CAGD,+BACC,YAAA,CAIF,6CACC,wBAAA,CACA,aAAA\",\"sourcesContent\":[\"\\n.dialog-row {\\n\\tdisplay: flex;\\n\\tjustify-content: end;\\n\\tmargin-top: 8px;\\n}\\n\\np {\\n\\t&.loading,\\n\\t&.loading-error {\\n\\t\\theight: 100px;\\n\\t}\\n\\n\\t&:last-child {\\n\\t\\tmargin-top: 10px;\\n\\t}\\n}\\n\\n.text-center {\\n\\ttext-align: center;\\n}\\n\\n.app {\\n\\tdisplay: flex;\\n\\tflex-direction: row;\\n\\n\\timg {\\n\\t\\theight: 50px;\\n\\t\\twidth: 50px;\\n\\t\\tfilter: var(--background-invert-if-dark);\\n\\t}\\n\\n\\timg, .info {\\n\\t\\tpadding: 12px;\\n\\t}\\n\\n\\t.info {\\n\\t\\th3, p {\\n\\t\\t\\ttext-align: start;\\n\\t\\t}\\n\\n\\t\\th3 {\\n\\t\\t\\tmargin-top: 0;\\n\\t\\t}\\n\\t}\\n\\n\\t.checkbox-radio-switch {\\n\\t\\tmargin-inline-start: auto;\\n\\t\\tpadding: 0 2px;\\n\\t}\\n}\\n\"],\"sourceRoot\":\"\"}]);\n// Exports\nexport default ___CSS_LOADER_EXPORT___;\n","// The module cache\nvar __webpack_module_cache__ = {};\n\n// The require function\nfunction __webpack_require__(moduleId) {\n\t// Check if module is in cache\n\tvar cachedModule = __webpack_module_cache__[moduleId];\n\tif (cachedModule !== undefined) {\n\t\treturn cachedModule.exports;\n\t}\n\t// Create a new module (and put it into the cache)\n\tvar module = __webpack_module_cache__[moduleId] = {\n\t\tid: moduleId,\n\t\tloaded: false,\n\t\texports: {}\n\t};\n\n\t// Execute the module function\n\t__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);\n\n\t// Flag the module as loaded\n\tmodule.loaded = true;\n\n\t// Return the exports of the module\n\treturn module.exports;\n}\n\n// expose the modules object (__webpack_modules__)\n__webpack_require__.m = __webpack_modules__;\n\n","// getDefaultExport function for compatibility with non-harmony modules\n__webpack_require__.n = (module) => {\n\tvar getter = module && module.__esModule ?\n\t\t() => (module['default']) :\n\t\t() => (module);\n\t__webpack_require__.d(getter, { a: getter });\n\treturn getter;\n};","// define getter functions for harmony exports\n__webpack_require__.d = (exports, definition) => {\n\tfor(var key in definition) {\n\t\tif(__webpack_require__.o(definition, key) && !__webpack_require__.o(exports, key)) {\n\t\t\tObject.defineProperty(exports, key, { enumerable: true, get: definition[key] });\n\t\t}\n\t}\n};","// The chunk loading function for additional chunks\n// Since all referenced chunks are already included\n// in this file, this function is empty here.\n__webpack_require__.e = () => (Promise.resolve());","__webpack_require__.g = (function() {\n\tif (typeof globalThis === 'object') return globalThis;\n\ttry {\n\t\treturn this || new Function('return this')();\n\t} catch (e) {\n\t\tif (typeof window === 'object') return window;\n\t}\n})();","__webpack_require__.o = (obj, prop) => (Object.prototype.hasOwnProperty.call(obj, prop))","// define __esModule on exports\n__webpack_require__.r = (exports) => {\n\tif(typeof Symbol !== 'undefined' && Symbol.toStringTag) {\n\t\tObject.defineProperty(exports, Symbol.toStringTag, { value: 'Module' });\n\t}\n\tObject.defineProperty(exports, '__esModule', { value: true });\n};","__webpack_require__.nmd = (module) => {\n\tmodule.paths = [];\n\tif (!module.children) module.children = [];\n\treturn module;\n};","__webpack_require__.j = 2696;","__webpack_require__.b = document.baseURI || self.location.href;\n\n// object to store loaded and loading chunks\n// undefined = chunk not loaded, null = chunk preloaded/prefetched\n// [resolve, reject, Promise] = chunk loading, 0 = chunk loaded\nvar installedChunks = {\n\t2696: 0\n};\n\n// no chunk on demand loading\n\n// no prefetching\n\n// no preloaded\n\n// no HMR\n\n// no HMR manifest\n\n__webpack_require__.O.j = (chunkId) => (installedChunks[chunkId] === 0);\n\n// install a JSONP callback for chunk loading\nvar webpackJsonpCallback = (parentChunkLoadingFunction, data) => {\n\tvar chunkIds = data[0];\n\tvar moreModules = data[1];\n\tvar runtime = data[2];\n\t// add \"moreModules\" to the modules object,\n\t// then flag all \"chunkIds\" as loaded and fire callback\n\tvar moduleId, chunkId, i = 0;\n\tif(chunkIds.some((id) => (installedChunks[id] !== 0))) {\n\t\tfor(moduleId in moreModules) {\n\t\t\tif(__webpack_require__.o(moreModules, moduleId)) {\n\t\t\t\t__webpack_require__.m[moduleId] = moreModules[moduleId];\n\t\t\t}\n\t\t}\n\t\tif(runtime) var result = runtime(__webpack_require__);\n\t}\n\tif(parentChunkLoadingFunction) parentChunkLoadingFunction(data);\n\tfor(;i < chunkIds.length; i++) {\n\t\tchunkId = chunkIds[i];\n\t\tif(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {\n\t\t\tinstalledChunks[chunkId][0]();\n\t\t}\n\t\tinstalledChunks[chunkId] = 0;\n\t}\n\treturn __webpack_require__.O(result);\n}\n\nvar chunkLoadingGlobal = self[\"webpackChunknextcloud\"] = self[\"webpackChunknextcloud\"] || [];\nchunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));\nchunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));","__webpack_require__.nc = undefined;","// startup\n// Load entry module and return exports\n// This entry module depends on other loaded chunks and execution need to be delayed\nvar __webpack_exports__ = __webpack_require__.O(undefined, [4208], () => (__webpack_require__(10440)))\n__webpack_exports__ = __webpack_require__.O(__webpack_exports__);\n"],"names":["deferred","user","getCurrentUser","getLoggerBuilder","setApp","build","setUid","uid","detectUser","Node","constructor","value","_defineProperty","this","_head","WeakMap","_tail","_size","Queue","_classPrivateFieldInitSpec","clear","enqueue","_this$size","node","_classPrivateFieldGet","next","_classPrivateFieldSet","dequeue","_this$size3","current","peek","undefined","size","Symbol","iterator","pLimit","concurrency","validateConcurrency","queue","activeCount","resumeNext","run","async","function_","resolve","arguments_","result","generator","_len","arguments","length","Array","_key","Promise","internalResolve","then","bind","Object","defineProperties","get","pendingCount","clearQueue","set","newConcurrency","queueMicrotask","Number","isInteger","POSITIVE_INFINITY","TypeError","recommended","calendar","description","t","icon","imagePath","contacts","mail","spreed","richdocuments","name","notes","richdocumentscode","hidden","recommendedIds","keys","components","NcCheckboxRadioSwitch","NcButton","data","showInstallButton","installingApps","loadingApps","loadingAppsError","apps","defaultPageUrl","loadState","computed","recommendedApps","filter","app","includes","id","isAnyAppSelected","some","isSelected","mounted","axios","generateUrl","logger","info","map","assign","loading","installationError","isCompatible","debug","error","methods","installApps","limit","installing","active","canInstall","post","appIds","groups","catch","all","window","location","customIcon","appId","warn","customName","customDescription","isHidden","toggleSelect","index","findIndex","$set","options","styleTagTransform","setAttributes","insert","domAPI","insertStyleElement","locals","_vm","_c","_self","staticClass","attrs","_v","_s","_e","_l","key","domProps","on","$event","__webpack_nonce__","getCSPNonce","Vue","mixin","extend","RecommendedApps","$mount","___CSS_LOADER_EXPORT___","push","module","__webpack_module_cache__","__webpack_require__","moduleId","cachedModule","exports","loaded","__webpack_modules__","call","m","O","chunkIds","fn","priority","notFulfilled","Infinity","i","fulfilled","j","every","splice","r","n","getter","__esModule","d","a","definition","o","defineProperty","enumerable","e","g","globalThis","Function","obj","prop","prototype","hasOwnProperty","toStringTag","nmd","paths","children","b","document","baseURI","self","href","installedChunks","chunkId","webpackJsonpCallback","parentChunkLoadingFunction","moreModules","runtime","chunkLoadingGlobal","forEach","nc","__webpack_exports__"],"sourceRoot":""} \ No newline at end of file