aboutsummaryrefslogtreecommitdiffstats
path: root/apps/settings/src/components/AppList
diff options
context:
space:
mode:
Diffstat (limited to 'apps/settings/src/components/AppList')
-rw-r--r--apps/settings/src/components/AppList/AppDaemonBadge.vue37
-rw-r--r--apps/settings/src/components/AppList/AppItem.vue81
-rw-r--r--apps/settings/src/components/AppList/AppLevelBadge.vue6
-rw-r--r--apps/settings/src/components/AppList/AppScore.vue2
4 files changed, 104 insertions, 22 deletions
diff --git a/apps/settings/src/components/AppList/AppDaemonBadge.vue b/apps/settings/src/components/AppList/AppDaemonBadge.vue
new file mode 100644
index 00000000000..ca81e7fab0b
--- /dev/null
+++ b/apps/settings/src/components/AppList/AppDaemonBadge.vue
@@ -0,0 +1,37 @@
+<!--
+ - SPDX-FileCopyrightText: 2024 Nextcloud GmbH and Nextcloud contributors
+ - SPDX-License-Identifier: AGPL-3.0-or-later
+-->
+<template>
+ <span v-if="daemon"
+ class="app-daemon-badge"
+ :title="daemon.name">
+ <NcIconSvgWrapper :path="mdiFileChart" :size="20" inline />
+ {{ daemon.display_name }}
+ </span>
+</template>
+
+<script setup lang="ts">
+import type { IDeployDaemon } from '../../app-types.ts'
+import { mdiFileChart } from '@mdi/js'
+import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
+
+defineProps<{
+ daemon?: IDeployDaemon
+}>()
+</script>
+
+<style scoped lang="scss">
+.app-daemon-badge {
+ color: var(--color-text-maxcontrast);
+ background-color: transparent;
+ border: 1px solid var(--color-text-maxcontrast);
+ border-radius: var(--border-radius);
+
+ display: flex;
+ flex-direction: row;
+ gap: 6px;
+ padding: 3px 6px;
+ width: fit-content;
+}
+</style>
diff --git a/apps/settings/src/components/AppList/AppItem.vue b/apps/settings/src/components/AppList/AppItem.vue
index 881be612445..95a98a93cde 100644
--- a/apps/settings/src/components/AppList/AppItem.vue
+++ b/apps/settings/src/components/AppList/AppItem.vue
@@ -14,9 +14,13 @@
<component :is="dataItemTag"
class="app-image app-image-icon"
:headers="getDataItemHeaders(`app-table-col-icon`)">
- <div v-if="(listView && !app.preview) || (!listView && !screenshotLoaded)" class="icon-settings-dark" />
+ <div v-if="!app?.app_api && shouldDisplayDefaultIcon" class="icon-settings-dark" />
+ <NcIconSvgWrapper v-else-if="app.app_api && shouldDisplayDefaultIcon"
+ :path="mdiCogOutline"
+ :size="listView ? 24 : 48"
+ style="min-width: auto; min-height: auto; height: 100%;" />
- <svg v-else-if="listView && app.preview"
+ <svg v-else-if="listView && app.preview && !app.app_api"
width="32"
height="32"
viewBox="0 0 32 32">
@@ -71,10 +75,11 @@
<div v-if="app.error" class="warning">
{{ app.error }}
</div>
- <div v-if="isLoading" class="icon icon-loading-small" />
+ <div v-if="isLoading || isInitializing" class="icon icon-loading-small" />
<NcButton v-if="app.update"
type="primary"
- :disabled="installing || isLoading"
+ :disabled="installing || isLoading || !defaultDeployDaemonAccessible || isManualInstall"
+ :title="updateButtonText"
@click.stop="update(app.id)">
{{ t('settings', 'Update to {update}', {update:app.update}) }}
</NcButton>
@@ -86,36 +91,46 @@
{{ t('settings', 'Remove') }}
</NcButton>
<NcButton v-if="app.active"
- :disabled="installing || isLoading"
+ :disabled="installing || isLoading || isInitializing || isDeploying"
@click.stop="disable(app.id)">
- {{ t('settings','Disable') }}
+ {{ disableButtonText }}
</NcButton>
<NcButton v-if="!app.active && (app.canInstall || app.isCompatible)"
:title="enableButtonTooltip"
:aria-label="enableButtonTooltip"
type="primary"
- :disabled="!app.canInstall || installing || isLoading"
- @click.stop="enable(app.id)">
+ :disabled="!app.canInstall || installing || isLoading || !defaultDeployDaemonAccessible || isInitializing || isDeploying"
+ @click.stop="enableButtonAction">
{{ enableButtonText }}
</NcButton>
<NcButton v-else-if="!app.active"
:title="forceEnableButtonTooltip"
:aria-label="forceEnableButtonTooltip"
type="secondary"
- :disabled="installing || isLoading"
+ :disabled="installing || isLoading || !defaultDeployDaemonAccessible"
@click.stop="forceEnable(app.id)">
{{ forceEnableButtonText }}
</NcButton>
+
+ <DaemonSelectionDialog v-if="app?.app_api && showSelectDaemonModal"
+ :show.sync="showSelectDaemonModal"
+ :app="app" />
</component>
</component>
</template>
<script>
+import { useAppsStore } from '../../store/apps-store.js'
+
import AppScore from './AppScore.vue'
import AppLevelBadge from './AppLevelBadge.vue'
import AppManagement from '../../mixins/AppManagement.js'
import SvgFilterMixin from '../SvgFilterMixin.vue'
-import NcButton from '@nextcloud/vue/dist/Components/NcButton.js'
+import NcButton from '@nextcloud/vue/components/NcButton'
+import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
+import { mdiCogOutline } from '@mdi/js'
+import { useAppApiStore } from '../../store/app-api-store.ts'
+import DaemonSelectionDialog from '../AppAPI/DaemonSelectionDialog.vue'
export default {
name: 'AppItem',
@@ -123,6 +138,8 @@ export default {
AppLevelBadge,
AppScore,
NcButton,
+ NcIconSvgWrapper,
+ DaemonSelectionDialog,
},
mixins: [AppManagement, SvgFilterMixin],
props: {
@@ -151,11 +168,22 @@ export default {
default: false,
},
},
+ setup() {
+ const store = useAppsStore()
+ const appApiStore = useAppApiStore()
+
+ return {
+ store,
+ appApiStore,
+ mdiCogOutline,
+ }
+ },
data() {
return {
isSelected: false,
scrolled: false,
screenshotLoaded: false,
+ showSelectDaemonModal: false,
}
},
computed: {
@@ -168,6 +196,9 @@ export default {
withSidebar() {
return !!this.$route.params.id
},
+ shouldDisplayDefaultIcon() {
+ return (this.listView && !this.app.preview) || (!this.listView && !this.screenshotLoaded)
+ },
},
watch: {
'$route.params.id'(id) {
@@ -195,6 +226,23 @@ export default {
getDataItemHeaders(columnName) {
return this.useBundleView ? [this.headers, columnName].join(' ') : null
},
+ showSelectionModal() {
+ this.showSelectDaemonModal = true
+ },
+ async enableButtonAction() {
+ if (!this.app?.app_api) {
+ this.enable(this.app.id)
+ return
+ }
+ await this.appApiStore.fetchDockerDaemons()
+ if (this.appApiStore.dockerDaemons.length === 1 && this.app.needsDownload) {
+ this.enable(this.app.id, this.appApiStore.dockerDaemons[0])
+ } else if (this.app.needsDownload) {
+ this.showSelectionModal()
+ } else {
+ this.enable(this.app.id, this.app.daemon)
+ }
+ },
},
}
</script>
@@ -228,7 +276,7 @@ export default {
.app-image {
width: var(--default-clickable-area);
height: auto;
- text-align: right;
+ text-align: end;
}
.app-image-icon svg,
@@ -257,8 +305,7 @@ export default {
.app-name--link::after {
content: '';
position: absolute;
- left: 0;
- right: 0;
+ inset-inline: 0;
height: var(--app-item-height);
}
@@ -271,7 +318,7 @@ export default {
.icon-loading-small {
display: inline-block;
top: 4px;
- margin-right: 10px;
+ margin-inline-end: 10px;
}
}
@@ -317,10 +364,8 @@ export default {
.app-name--link::after {
content: '';
position: absolute;
- top: 0;
- left: 0;
- right: 0;
- bottom: 0;
+ inset-block: 0;
+ inset-inline: 0;
}
.app-actions {
diff --git a/apps/settings/src/components/AppList/AppLevelBadge.vue b/apps/settings/src/components/AppList/AppLevelBadge.vue
index cceb5b0ecf9..8461f5eb6b9 100644
--- a/apps/settings/src/components/AppList/AppLevelBadge.vue
+++ b/apps/settings/src/components/AppList/AppLevelBadge.vue
@@ -13,9 +13,9 @@
</template>
<script setup lang="ts">
-import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
+import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
-import { mdiCheck, mdiStarShooting } from '@mdi/js'
+import { mdiCheck, mdiStarShootingOutline } from '@mdi/js'
import { translate as t } from '@nextcloud/l10n'
import { computed } from 'vue'
@@ -28,7 +28,7 @@ const props = defineProps<{
const isSupported = computed(() => props.level === 300)
const isFeatured = computed(() => props.level === 200)
-const badgeIcon = computed(() => isSupported.value ? mdiStarShooting : mdiCheck)
+const badgeIcon = computed(() => isSupported.value ? mdiStarShootingOutline : mdiCheck)
const badgeText = computed(() => isSupported.value ? t('settings', 'Supported') : t('settings', 'Featured'))
const badgeTitle = computed(() => isSupported.value
? t('settings', 'This app is supported via your current Nextcloud subscription.')
diff --git a/apps/settings/src/components/AppList/AppScore.vue b/apps/settings/src/components/AppList/AppScore.vue
index 7eebc620a0b..a1dd4c03842 100644
--- a/apps/settings/src/components/AppList/AppScore.vue
+++ b/apps/settings/src/components/AppList/AppScore.vue
@@ -20,7 +20,7 @@
</span>
</template>
<script lang="ts">
-import NcIconSvgWrapper from '@nextcloud/vue/dist/Components/NcIconSvgWrapper.js'
+import NcIconSvgWrapper from '@nextcloud/vue/components/NcIconSvgWrapper'
import { mdiStar, mdiStarHalfFull, mdiStarOutline } from '@mdi/js'
import { translate as t } from '@nextcloud/l10n'
import { defineComponent } from 'vue'