Merge pull request #10103 from nextcloud/bugfix/9767/apps-management-issues

Fix remaining apps management issues
This commit is contained in:
Morris Jobke 2018-07-05 10:37:26 +02:00 committed by GitHub
commit 86d9528bc9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
10 changed files with 56 additions and 29 deletions

View File

@ -989,10 +989,15 @@ span.version {
.section { .section {
cursor: pointer; cursor: pointer;
} }
.app-list-move {
transition: transform 1s;
}
&.installed { &.installed {
.apps-list-container {
display: table; display: table;
width: 100%; width: 100%;
height: auto; height: auto;
}
margin-bottom: 100px; margin-bottom: 100px;
.section { .section {
display: table-row; display: table-row;

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -60,7 +60,8 @@
<multiselect v-if="isLimitedToGroups(app)" :options="groups" :value="appGroups" @select="addGroupLimitation" @remove="removeGroupLimitation" :options-limit="5" <multiselect v-if="isLimitedToGroups(app)" :options="groups" :value="appGroups" @select="addGroupLimitation" @remove="removeGroupLimitation" :options-limit="5"
:placeholder="t('settings', 'Limit app usage to groups')" :placeholder="t('settings', 'Limit app usage to groups')"
label="name" track-by="id" class="multiselect-vue" label="name" track-by="id" class="multiselect-vue"
:multiple="true" :close-on-select="false"> :multiple="true" :close-on-select="false"
@search-change="asyncFindGroup">
<span slot="noResult">{{t('settings', 'No results')}}</span> <span slot="noResult">{{t('settings', 'No results')}}</span>
</multiselect> </multiselect>
</div> </div>

View File

@ -24,9 +24,13 @@
<div id="app-content-inner"> <div id="app-content-inner">
<div id="apps-list" :class="{installed: (useBundleView || useListView), store: useAppStoreView}"> <div id="apps-list" :class="{installed: (useBundleView || useListView), store: useAppStoreView}">
<template v-if="useListView"> <template v-if="useListView">
<transition-group name="app-list" tag="div" class="apps-list-container">
<app-item v-for="app in apps" :key="app.id" :app="app" :category="category" /> <app-item v-for="app in apps" :key="app.id" :app="app" :category="category" />
</transition-group>
</template> </template>
<template v-for="bundle in bundles" v-if="useBundleView && bundleApps(bundle.id).length > 0"> <template v-for="bundle in bundles" v-if="useBundleView && bundleApps(bundle.id).length > 0">
<transition-group name="app-list" tag="div" class="apps-list-container">
<div class="apps-header" :key="bundle.id"> <div class="apps-header" :key="bundle.id">
<div class="app-image"></div> <div class="app-image"></div>
<h2>{{ bundle.name }} <input type="button" :value="bundleToggleText(bundle.id)" v-on:click="toggleBundle(bundle.id)"></h2> <h2>{{ bundle.name }} <input type="button" :value="bundleToggleText(bundle.id)" v-on:click="toggleBundle(bundle.id)"></h2>
@ -36,6 +40,7 @@
<div class="actions">&nbsp;</div> <div class="actions">&nbsp;</div>
</div> </div>
<app-item v-for="app in bundleApps(bundle.id)" :key="bundle.id + app.id" :app="app" :category="category"/> <app-item v-for="app in bundleApps(bundle.id)" :key="bundle.id + app.id" :app="app" :category="category"/>
</transition-group>
</template> </template>
<template v-if="useAppStoreView"> <template v-if="useAppStoreView">
<app-item v-for="app in apps" :key="app.id" :app="app" :category="category" :list-view="false" /> <app-item v-for="app in apps" :key="app.id" :app="app" :category="category" :list-view="false" />
@ -96,7 +101,7 @@ export default {
return apps.filter(app => app.installed); return apps.filter(app => app.installed);
} }
if (this.category === 'enabled') { if (this.category === 'enabled') {
return apps.filter(app => app.active); return apps.filter(app => app.active && app.installed);
} }
if (this.category === 'disabled') { if (this.category === 'disabled') {
return apps.filter(app => !app.active && app.installed); return apps.filter(app => !app.active && app.installed);

View File

@ -51,10 +51,10 @@
<div class="actions"> <div class="actions">
<div class="warning" v-if="app.error">{{ app.error }}</div> <div class="warning" v-if="app.error">{{ app.error }}</div>
<div class="icon icon-loading-small" v-if="loading(app.id)"></div> <div class="icon icon-loading-small" v-if="loading(app.id)"></div>
<input v-if="app.update" class="update" type="button" :value="t('settings', 'Update to {update}', {update:app.update})" v-on:click="update(app.id)" :disabled="installing || loading(app.id)" /> <input v-if="app.update" class="update" type="button" :value="t('settings', 'Update to {update}', {update:app.update})" v-on:click.stop="update(app.id)" :disabled="installing || loading(app.id)" />
<input v-if="app.canUnInstall" class="uninstall" type="button" :value="t('settings', 'Remove')" v-on:click="remove(app.id)" :disabled="installing || loading(app.id)" /> <input v-if="app.canUnInstall" class="uninstall" type="button" :value="t('settings', 'Remove')" v-on:click.stop="remove(app.id)" :disabled="installing || loading(app.id)" />
<input v-if="app.active" class="enable" type="button" :value="t('settings','Disable')" v-on:click="disable(app.id)" :disabled="installing || loading(app.id)" /> <input v-if="app.active" class="enable" type="button" :value="t('settings','Disable')" v-on:click.stop="disable(app.id)" :disabled="installing || loading(app.id)" />
<input v-if="!app.active" class="enable" type="button" :value="enableButtonText" v-on:click="enable(app.id)" v-tooltip.auto="enableButtonTooltip" :disabled="!app.canInstall || installing || loading(app.id)" /> <input v-if="!app.active" class="enable" type="button" :value="enableButtonText" v-on:click.stop="enable(app.id)" v-tooltip.auto="enableButtonTooltip" :disabled="!app.canInstall || installing || loading(app.id)" />
</div> </div>
</div> </div>
</template> </template>

View File

@ -54,6 +54,9 @@
} }
}, },
methods: { methods: {
asyncFindGroup(query) {
return this.$store.dispatch('getGroups', {search: query, limit: 5, offset: 0});
},
isLimitedToGroups(app) { isLimitedToGroups(app) {
if (this.app.groups.length || this.groupCheckedAppsData) { if (this.app.groups.length || this.groupCheckedAppsData) {
return true; return true;

View File

@ -62,8 +62,13 @@ const mutations = {
}, },
setError(state, {appId, error}) { setError(state, {appId, error}) {
let app = state.apps.find(app => app.id === appId); if (!Array.isArray(appId)) {
appId = [appId];
}
appId.forEach((_id) => {
let app = state.apps.find(app => app.id === _id);
app.error = error; app.error = error;
});
}, },
clearError(state, {appId, error}) { clearError(state, {appId, error}) {
@ -90,6 +95,7 @@ const mutations = {
state.apps.find(app => app.id === appId).active = false; state.apps.find(app => app.id === appId).active = false;
state.apps.find(app => app.id === appId).groups = []; state.apps.find(app => app.id === appId).groups = [];
state.apps.find(app => app.id === appId).needsDownload = true; state.apps.find(app => app.id === appId).needsDownload = true;
state.apps.find(app => app.id === appId).installed = false;
state.apps.find(app => app.id === appId).canUnInstall = false; state.apps.find(app => app.id === appId).canUnInstall = false;
state.apps.find(app => app.id === appId).canInstall = true; state.apps.find(app => app.id === appId).canInstall = true;
}, },
@ -198,10 +204,13 @@ const actions = {
}); });
}) })
.catch((error) => { .catch((error) => {
context.commit('setError', {appId: apps, error: t('settings', 'Error while enabling app')});
context.commit('stopLoading', apps); context.commit('stopLoading', apps);
context.commit('stopLoading', 'install'); context.commit('stopLoading', 'install');
context.commit('APPS_API_FAILURE', { appId, error }) context.commit('setError', {
appId: apps,
error: error.response.data.data.message
});
context.commit('APPS_API_FAILURE', { appId, error});
}) })
}).catch((error) => context.commit('API_FAILURE', { appId, error })); }).catch((error) => context.commit('API_FAILURE', { appId, error }));
}, },

View File

@ -74,6 +74,9 @@ const mutations = {
}, },
addGroup(state, {gid, displayName}) { addGroup(state, {gid, displayName}) {
try { try {
if (typeof state.groups.find((group) => group.id === gid) !== 'undefined') {
return;
}
// extend group to default values // extend group to default values
let group = Object.assign({}, defaults.group, { let group = Object.assign({}, defaults.group, {
id: gid, id: gid,
@ -223,7 +226,8 @@ const actions = {
getGroups(context, { offset, limit, search }) { getGroups(context, { offset, limit, search }) {
search = typeof search === 'string' ? search : ''; search = typeof search === 'string' ? search : '';
return api.get(OC.linkToOCS(`cloud/groups?offset=${offset}&limit=${limit}&search=${search}`, 2)) let limitParam = limit === -1 ? '' : `&limit=${limit}`;
return api.get(OC.linkToOCS(`cloud/groups?offset=${offset}&search=${search}${limitParam}`, 2))
.then((response) => { .then((response) => {
if (Object.keys(response.data.ocs.data.groups).length > 0) { if (Object.keys(response.data.ocs.data.groups).length > 0) {
response.data.ocs.data.groups.forEach(function(group) { response.data.ocs.data.groups.forEach(function(group) {

View File

@ -73,7 +73,7 @@ export default {
beforeMount() { beforeMount() {
this.$store.dispatch('getCategories'); this.$store.dispatch('getCategories');
this.$store.dispatch('getAllApps'); this.$store.dispatch('getAllApps');
this.$store.dispatch('getGroups', {offset: 0, limit: -1}); this.$store.dispatch('getGroups', {offset: 0, limit: 5});
this.$store.commit('setUpdateCount', this.$store.getters.getServerData.updateCount) this.$store.commit('setUpdateCount', this.$store.getters.getServerData.updateCount)
}, },
mounted() { mounted() {