Skip to content

Commit

Permalink
ExApps management and Admin settings UI logic fixes (#177)
Browse files Browse the repository at this point in the history
Resolves: #171 

Also fixes:

* Update button in UI not working.

---------

Signed-off-by: Andrey Borysenko <andrey18106x@gmail.com>
Co-authored-by: Alexander Piskun <bigcat88@icloud.com>
Co-authored-by: Alexander Piskun <13381981+bigcat88@users.noreply.github.com>
  • Loading branch information
3 people committed Dec 21, 2023
1 parent c6292da commit 3e1e758
Show file tree
Hide file tree
Showing 11 changed files with 123 additions and 38 deletions.
3 changes: 2 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).

## [Unreleased]

## [1.4.4 - 2023-12-2x]
## [1.4.4 - 2023-12-21]

### Added

Expand All @@ -18,6 +18,7 @@ and this project adheres to [Semantic Versioning](http://semver.org/).
- Processing of invalid default Nextcloud URL/incorrect url with slash at the end. #169
- `occ app_api:app:register` error message in case of missing deploy of ExApp. #172
- Default Docker Daemon(`not for AIO`) configuration should be better now. #173
- UI fixes: `Update` button not working in some cases, missed `Uninstall` button. #177

## [1.4.3 - 2023-12-18]

Expand Down
2 changes: 1 addition & 1 deletion appinfo/info.xml
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ to join us in shaping a more versatile, stable, and secure app landscape.
*Your insights, suggestions, and contributions are invaluable to us.*
]]></description>
<version>1.4.3</version>
<version>1.4.4</version>
<licence>agpl</licence>
<author mail="andrey18106x@gmail.com" homepage="https://github.com/andrey18106">Andrey Borysenko</author>
<author mail="bigcat88@icloud.com" homepage="https://github.com/bigcat88">Alexander Piskun</author>
Expand Down
17 changes: 11 additions & 6 deletions lib/Controller/ExAppsPageController.php
Original file line number Diff line number Diff line change
Expand Up @@ -380,14 +380,14 @@ private function buildLocalAppsList(array $apps, array $exApps): array {
'level' => 100,
'missingMaxOwnCloudVersion' => false,
'missingMinOwnCloudVersion' => false,
'canInstall' => true,
'canUnInstall' => false,
'canInstall' => true, // to allow "remove" command for manual-install
'canUnInstall' => !($exApp->getEnabled() === 1),
'isCompatible' => true,
'screenshot' => '',
'score' => 0,
'ratingNumOverall' => 0,
'ratingNumThresholdReached' => false,
'removable' => false,
'removable' => true, // to allow "remove" command for manual-install
'active' => $exApp->getEnabled() === 1,
'needsDownload' => false,
'groups' => [],
Expand Down Expand Up @@ -468,15 +468,16 @@ public function enableApps(array $appIds, array $groups = []): JSONResponse {
], Http::STATUS_INTERNAL_SERVER_ERROR);
}

//if (!$this->service->enableExApp($exApp)) {
// return new JSONResponse(['data' => ['message' => $this->l10n->t('Failed to enable ExApp')]], Http::STATUS_INTERNAL_SERVER_ERROR);
//}
$scopes = $this->exAppApiScopeService->mapScopeGroupsToNames(array_map(function (ExAppScope $exAppScope) {
return $exAppScope->getScopeGroup();
}, $this->exAppScopeService->getExAppScopes($exApp)));
return new JSONResponse([
'data' => [
'daemon_config' => $daemonConfig,
'systemApp' => $this->exAppUsersService->exAppUserExists($exApp->getAppid(), ''),
'exAppUrl' => AppAPIService::getExAppUrl($exApp->getProtocol(), $exApp->getHost(), $exApp->getPort()),
'status' => json_decode($exApp->getStatus(), true),
'scopes' => $scopes,
]
]);
}
Expand Down Expand Up @@ -662,12 +663,16 @@ public function updateApp(string $appId): JSONResponse {
}
}

$scopes = $this->exAppApiScopeService->mapScopeGroupsToNames(array_map(function (ExAppScope $exAppScope) {
return $exAppScope->getScopeGroup();
}, $this->exAppScopeService->getExAppScopes($exApp)));
return new JSONResponse([
'data' => [
'appid' => $appId,
'status' => ['progress' => 0],
'systemApp' => filter_var($exAppInfo['system_app'], FILTER_VALIDATE_BOOLEAN),
'exAppUrl' => AppAPIService::getExAppUrl($exAppInfo['protocol'], $exAppInfo['host'], (int) $exAppInfo['port']),
'scopes' => $scopes,
]
]);
}
Expand Down
2 changes: 1 addition & 1 deletion lib/DeployActions/DockerActions.php
Original file line number Diff line number Diff line change
Expand Up @@ -339,7 +339,7 @@ public function buildDeployParams(DaemonConfig $daemonConfig, SimpleXMLElement $
$secret = $oldEnvs['APP_SECRET'];
$storage = $oldEnvs['APP_PERSISTENT_STORAGE'];
// Preserve previous device requests (GPU)
$deviceRequests = $containerInfo['HostConfig']['DeviceRequests'];
$deviceRequests = $containerInfo['HostConfig']['DeviceRequests'] ?? [];
} else {
$port = $this->service->getExAppRandomPort();
if (isset($deployConfig['gpu']) && filter_var($deployConfig['gpu'], FILTER_VALIDATE_BOOLEAN)) {
Expand Down
2 changes: 1 addition & 1 deletion src/components/Apps/AppDetails.vue
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@
<input v-if="app.active"
class="enable"
type="button"
:value="t('settings','Disable')"
:value="disableButtonText"
:disabled="installing || isLoading || !defaultDeployDaemonAccessible || isInitializing"
@click="disable(app.id)">
<input v-if="!app.active && (app.canInstall || app.isCompatible)"
Expand Down
2 changes: 1 addition & 1 deletion src/components/Apps/AppItem.vue
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@
<NcButton v-if="app.active"
:disabled="installing || isLoading || !defaultDeployDaemonAccessible || isInitializing"
@click.stop="disable(app.id)">
{{ t('settings','Disable') }}
{{ disableButtonText }}
</NcButton>
<NcButton v-if="!app.active && (app.canInstall || app.isCompatible)"
:title="enableButtonTooltip"
Expand Down
59 changes: 48 additions & 11 deletions src/components/DaemonConfig/DaemonConfig.vue
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
</template>
{{ !isDefault ? t('app_api', 'Set as default') : t('app_api', 'Default') }}
</NcActionButton>
<NcActionButton icon="icon-delete" @click="deleteDaemonConfig(daemon)">
<NcActionButton icon="icon-delete" :close-after-click="true" @click="deleteDaemonConfig(daemon)">
{{ t('app_api', 'Delete') }}
<template #icon>
<NcLoadingIcon v-if="deleting" :size="20" />
Expand All @@ -31,6 +31,35 @@
:show.sync="showDetailsModal"
:daemon="daemon"
:is-default="isDefault" />
<NcDialog
v-show="showDeleteDialog"
style="padding: 20px;"
:open.sync="showDeleteDialog"
:content-classes="'confirm-delete-dialog'"
:name="t('app_api', 'Confirm deletion')">
<template #actions>
<NcDialogButton :label="t('app_api', 'Cancel')" :callback="() => showDeleteDialog = false">
<template #icon>
<Cancel :size="20" />
</template>
</NcDialogButton>
<NcDialogButton :label="t('app_api', 'Ok')" :callback="() => _deleteDaemonConfig(daemon)">
<template #icon>
<Check :size="20" />
</template>
</NcDialogButton>
</template>
<template #default>
<div class="confirm-delete-dialog">
<p>{{ t('app_api', 'Are you sure you want delete Deploy Daemon?') }}</p>
<NcNoteCard>
<template #default>
{{ t('app_api', 'This action will not remove installed ExApps on this daemon') }}
</template>
</NcNoteCard>
</div>
</template>
</NcDialog>
</div>
</template>

Expand All @@ -39,6 +68,11 @@ import axios from '@nextcloud/axios'
import { generateUrl } from '@nextcloud/router'
import { showError } from '@nextcloud/dialogs'
import NcListItem from '@nextcloud/vue/dist/Components/NcListItem.js'
import NcDialog from '@nextcloud/vue/dist/Components/NcDialog.js'
import NcDialogButton from '@nextcloud/vue/dist/Components/NcDialogButton.js'
import Cancel from 'vue-material-design-icons/Cancel.vue'
import Check from 'vue-material-design-icons/Check.vue'
import NcNoteCard from '@nextcloud/vue/dist/Components/NcNoteCard.js'
import NcActionButton from '@nextcloud/vue/dist/Components/NcActionButton.js'
import NcLoadingIcon from '@nextcloud/vue/dist/Components/NcLoadingIcon.js'
Expand All @@ -53,6 +87,11 @@ export default {
NcActionButton,
NcLoadingIcon,
CheckBold,
NcDialog,
NcDialogButton,
Cancel,
Check,
NcNoteCard,
DaemonConfigDetailsModal,
},
props: {
Expand Down Expand Up @@ -80,6 +119,7 @@ export default {
showDetailsModal: false,
settingDefault: false,
deleting: false,
showDeleteDialog: false,
}
},
computed: {
Expand Down Expand Up @@ -109,16 +149,7 @@ export default {
})
},
deleteDaemonConfig(daemon) {
const self = this
OC.dialogs.confirm(
t('app_api', 'Are you sure you want delete Deploy Daemon?'),
t('app_api', 'Confirm Deploy daemon deletion'),
function(success) {
if (success) {
self._deleteDaemonConfig(daemon)
}
},
)
this.showDeleteDialog = true
},
_deleteDaemonConfig(daemon) {
this.deleting = true
Expand All @@ -128,10 +159,12 @@ export default {
this.getAllDaemons()
}
this.deleting = false
this.showDetailsModal = false
})
.catch(err => {
console.debug(err)
this.deleting = false
this.showDetailsModal = false
})
},
},
Expand All @@ -143,4 +176,8 @@ export default {
background-color: var(--color-background-dark);
border-radius: var(--border-radius-pill);
}
.confirm-delete-dialog {
padding: 20px;
}
</style>
31 changes: 24 additions & 7 deletions src/components/DaemonConfig/RegisterDaemonConfigModal.vue
Original file line number Diff line number Diff line change
Expand Up @@ -71,7 +71,7 @@
:placeholder="t('app_api', 'Set daemon as default')"
:aria-label="t('app_api', 'Set daemon as default')"
style="margin-top: 1rem;">
{{ t('app_api', 'Default daemon') }}
{{ t('app_api', 'Set as default daemon') }}
</NcCheckboxRadioSwitch>
<template v-if="acceptsDeployId !== 'manual-install'">
<NcButton :aria-label="t('app_api', 'Deploy config')" style="margin: 10px 0;" @click="deployConfigSettingsOpened = !deployConfigSettingsOpened">
Expand All @@ -87,17 +87,27 @@
<NcInputField
id="deploy-config-net"
:value.sync="deployConfig.net"
:placeholder="t('app_api', 'Docker network name (default: host)')"
:aria-label="t('app_api', 'Docker network name (default: host)')"
:helper-text="t('app_api', 'Docker network name (default: host)')" />
:placeholder="t('app_api', 'Docker network name')"
:aria-label="t('app_api', 'Docker network name')"
:helper-text="t('app_api', 'Docker network name')" />
</div>
<div class="external-label">
<label for="deploy-config-host">{{ t('app_api', 'Host') }}</label>
<NcInputField
v-if="deployConfig.net === 'host'"
id="deploy-config-host"
:value.sync="deployConfig.host"
:placeholder="t('app_api', 'Hostname to reach ExApp (optional)')"
:aria-label="t('app_api', 'Hostname to reach ExApp (optional)')"
:helper-text="t('app_api', 'Hostname to reach ExApp (optional)')" />
</div>
<NcCheckboxRadioSwitch
id="deploy-config-gpus"
:checked.sync="deployConfig.gpu"
:placeholder="t('app_api', 'Enable gpus support (attach gpu to ExApp containers)')"
:aria-label="t('app_api', 'Enable gpus support (attach gpu to ExApp containers))')"
style="margin-top: 1rem;">
{{ t('app_api', 'GPUs support') }}
{{ t('app_api', 'Enable GPUs support') }}
</NcCheckboxRadioSwitch>
<p v-if="deployConfig.gpu" class="hint">
{{ t('app_api', 'All GPU devices will be requested to be enabled in ExApp containers') }}
Expand Down Expand Up @@ -173,7 +183,7 @@ export default {
deployConfigSettingsOpened: false,
deployConfig: {
net: 'host',
host: '',
host: 'localhost',
ssl_key: '',
ssl_key_password: '',
ssl_cert: '',
Expand Down Expand Up @@ -205,6 +215,13 @@ export default {
this.displayName = 'Docker Local'
}
},
'deployConfig.net'(newNet) {
if (newNet === 'host') {
this.deployConfig.host = 'localhost'
} else {
this.deployConfig.host = ''
}
},
},
methods: {
registerDaemon() {
Expand Down Expand Up @@ -269,7 +286,7 @@ export default {
this.deployConfigSettingsOpened = false
this.deployConfig = {
net: 'host',
host: '',
host: 'localhost',
ssl_key: '',
ssl_key_password: '',
ssl_cert: '',
Expand Down
10 changes: 5 additions & 5 deletions src/constants/AppsConstants.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,9 +2,9 @@ import { translate as t } from '@nextcloud/l10n'

/** Enum of verification constants, according to Apps */
export const APPS_SECTION_ENUM = Object.freeze({
enabled: t('settings', 'Active apps'),
disabled: t('settings', 'Disabled apps'),
updates: t('settings', 'Updates'),
featured: t('settings', 'Featured apps'),
supported: t('settings', 'Supported apps'), // From subscription
enabled: t('app_api', 'Active apps'),
disabled: t('app_api', 'Disabled apps'),
updates: t('app_api', 'Updates'),
featured: t('app_api', 'Featured apps'),
supported: t('app_api', 'Supported apps'), // From subscription
})
14 changes: 13 additions & 1 deletion src/mixins/AppManagement.js
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,12 @@ export default {
}
return t('app_api', 'Enable')
},
disableButtonText() {
if (this.app && Object.hasOwn(this.app?.status, 'progress')) {
return t('app_api', '{progress}% Initializing', { progress: this.app.status?.progress })
}
return t('app_api', 'Disable')
},
forceEnableButtonText() {
if (this.app.needsDownload) {
return t('app_api', 'Allow untested app')
Expand All @@ -44,7 +50,13 @@ export default {
return base
},
defaultDeployDaemonAccessible() {
return this.$store.getters.getDaemonAccessible || false
if (this.app?.daemon && this.app?.daemon?.accepts_deploy_id === 'manual-install') {
return true
}
if (this.app?.daemon?.accepts_deploy_id === 'docker-install') {
return this.$store.getters.getDaemonAccessible === true
}
return this.$store.getters.getDaemonAccessible
},
},

Expand Down
Loading

0 comments on commit 3e1e758

Please sign in to comment.