app.error.details is gone, should have never happened

Check BoxError.toPlainObject() for more
This commit is contained in:
Johannes Zellner
2025-10-17 19:45:41 +02:00
parent f14a7808cb
commit 42887fb1d9
8 changed files with 23 additions and 23 deletions

View File

@@ -137,7 +137,7 @@ onMounted(async () => {
<br/> <br/>
<form @submit.prevent="onSendmailSubmit()" autocomplete="off"> <form @submit.prevent="onSendmailSubmit()" autocomplete="off">
<fieldset :disabled="enableMailbox === 0 || sendmailBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId"> <fieldset :disabled="enableMailbox === 0 || sendmailBusy || (app.error && app.error.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId">
<input type="submit" style="display: none;" :disabled="!sendmailMailboxName"/> <input type="submit" style="display: none;" :disabled="!sendmailMailboxName"/>
<FormGroup> <FormGroup>
@@ -160,7 +160,7 @@ onMounted(async () => {
</FormGroup> </FormGroup>
<br/> <br/>
<Button @click="onSendmailSubmit()" :loading="sendmailBusy" :disabled="sendmailBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId">{{ $t('app.email.from.saveAction') }}</Button> <Button @click="onSendmailSubmit()" :loading="sendmailBusy" :disabled="sendmailBusy || (app.error && app.error.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId">{{ $t('app.email.from.saveAction') }}</Button>
</div> </div>
<hr style="margin-top: 20px" v-if="hasSendmail && hasRecvmail"/> <hr style="margin-top: 20px" v-if="hasSendmail && hasRecvmail"/>
@@ -184,7 +184,7 @@ onMounted(async () => {
</FormGroup> </FormGroup>
<br/> <br/>
<Button @click="onRecvmailSubmit()" :disabled="recvmailBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId" :loading="recvmailBusy">{{ $t('app.email.from.saveAction') }}</Button> <Button @click="onRecvmailSubmit()" :disabled="recvmailBusy || (app.error && app.error.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId" :loading="recvmailBusy">{{ $t('app.email.from.saveAction') }}</Button>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -189,7 +189,7 @@ onMounted(async () => {
<div> <div>
<form @submit.prevent="onSubmit()" autocomplete="off" novalidate> <form @submit.prevent="onSubmit()" autocomplete="off" novalidate>
<fieldset :disabled="busy"> <fieldset :disabled="busy">
<input type="submit" style="display: none;" :disabled="(app.error && app.error.details.installationState !== ISTATES.PENDING_LOCATION_CHANGE) || app.taskId || !formValid"/> <input type="submit" style="display: none;" :disabled="(app.error && app.error.installationState !== ISTATES.PENDING_LOCATION_CHANGE) || app.taskId || !formValid"/>
<FormGroup> <FormGroup>
<label>{{ $t('app.location.location') }}</label> <label>{{ $t('app.location.location') }}</label>
@@ -262,6 +262,6 @@ onMounted(async () => {
<Checkbox v-if="needsOverwriteDns" v-model="overwriteDns" :label="$t('app.location.dnsoverwrite')"/> <Checkbox v-if="needsOverwriteDns" v-model="overwriteDns" :label="$t('app.location.dnsoverwrite')"/>
<br/> <br/>
<Button @click="onSubmit()" :loading="busy" :disabled="busy || (app.error && app.error.details.installationState !== ISTATES.PENDING_LOCATION_CHANGE) || app.taskId || !formValid">{{ $t('app.location.saveAction') }}</Button> <Button @click="onSubmit()" :loading="busy" :disabled="busy || (app.error && app.error.installationState !== ISTATES.PENDING_LOCATION_CHANGE) || app.taskId || !formValid">{{ $t('app.location.saveAction') }}</Button>
</div> </div>
</template> </template>

View File

@@ -73,7 +73,7 @@ onMounted(() => {
<label>{{ $t('app.repair.recovery.title') }}</label> <label>{{ $t('app.repair.recovery.title') }}</label>
<div v-html="$t('app.repair.recovery.description', { docsLink: 'https://docs.cloudron.io/apps/#recovery-mode' })"></div> <div v-html="$t('app.repair.recovery.description', { docsLink: 'https://docs.cloudron.io/apps/#recovery-mode' })"></div>
<br/> <br/>
<Button @click="onToggleDebugMode" :disabled="debugModeBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_DEBUG) || app.taskId"> <Button @click="onToggleDebugMode" :disabled="debugModeBusy || (app.error && app.error.installationState !== ISTATES.PENDING_DEBUG) || app.taskId">
<span v-if="app.debugMode">{{ $t('app.repair.recovery.disableAction') }}</span> <span v-if="app.debugMode">{{ $t('app.repair.recovery.disableAction') }}</span>
<span v-else>{{ $t('app.repair.recovery.enableAction') }}</span> <span v-else>{{ $t('app.repair.recovery.enableAction') }}</span>
</Button> </Button>
@@ -84,9 +84,9 @@ onMounted(() => {
<div> <div>
<label>{{ $t('app.repair.taskError.title') }}</label> <label>{{ $t('app.repair.taskError.title') }}</label>
<div>{{ $t('app.repair.taskError.description') }}</div> <div>{{ $t('app.repair.taskError.description') }}</div>
<div v-if="app.error" style="margin-top: 10px;">An error occurred during the <b>{{ taskNameFromInstallationState(app.error.details.installationState) }}</b> operation: <span class="text-danger"><b>{{ app.error.reason + ': ' + app.error.message }}</b></span></div> <div v-if="app.error" style="margin-top: 10px;">An error occurred during the <b>{{ taskNameFromInstallationState(app.error.installationState) }}</b> operation: <span class="text-danger"><b>{{ app.error.reason + ': ' + app.error.message }}</b></span></div>
<br/> <br/>
<Button @click="onRepair()" :disabled="busyRepair || app.taskId || !app.error" :loading="busyRepair">{{ $t('app.repair.taskError.retryAction', { task: app.error ? taskNameFromInstallationState(app.error.details.installationState) : '' }) }}</Button> <Button @click="onRepair()" :disabled="busyRepair || app.taskId || !app.error" :loading="busyRepair">{{ $t('app.repair.taskError.retryAction', { task: app.error ? taskNameFromInstallationState(app.error.installationState) : '' }) }}</Button>
</div> </div>
</div> </div>
</template> </template>

View File

@@ -122,7 +122,7 @@ onMounted(async () => {
</datalist> </datalist>
</FormGroup> </FormGroup>
<br/> <br/>
<Button @click="onSubmitMemoryLimit()" :loading="memoryLimitBusy" :disabled="memoryLimitBusy || (!app.error && memoryLimit === currentMemoryLimit) || (app.error && app.error.details.installationState !== ISTATES.PENDING_RESIZE) || app.taskId">{{ $t('app.resources.memory.resizeAction') }}</Button> <Button @click="onSubmitMemoryLimit()" :loading="memoryLimitBusy" :disabled="memoryLimitBusy || (!app.error && memoryLimit === currentMemoryLimit) || (app.error && app.error.installationState !== ISTATES.PENDING_RESIZE) || app.taskId">{{ $t('app.resources.memory.resizeAction') }}</Button>
<hr style="margin-top: 20px"/> <hr style="margin-top: 20px"/>
@@ -137,12 +137,12 @@ onMounted(async () => {
</datalist> </datalist>
</FormGroup> </FormGroup>
<br/> <br/>
<Button @click="onSubmitCpuQuota()" :loading="cpuQuotaBusy" :disabled="cpuQuotaBusy || (!app.error && cpuQuota === currentCpuQuota) || (app.error && app.error.details.installationState !== ISTATES.PENDING_RESIZE) || app.taskId">{{ $t('app.resources.cpu.setAction') }}</Button> <Button @click="onSubmitCpuQuota()" :loading="cpuQuotaBusy" :disabled="cpuQuotaBusy || (!app.error && cpuQuota === currentCpuQuota) || (app.error && app.error.installationState !== ISTATES.PENDING_RESIZE) || app.taskId">{{ $t('app.resources.cpu.setAction') }}</Button>
<hr style="margin-top: 20px"/> <hr style="margin-top: 20px"/>
<form @submit.prevent="onSubmitDevices()" autocomplete="off"> <form @submit.prevent="onSubmitDevices()" autocomplete="off">
<fieldset :disabled="devicesBusy || (!app.error && !devicesChanged) || (app.error && app.error.details.installationState !== ISTATES.PENDING_RECREATE_CONTAINER) || app.taskId"> <fieldset :disabled="devicesBusy || (!app.error && !devicesChanged) || (app.error && app.error.installationState !== ISTATES.PENDING_RECREATE_CONTAINER) || app.taskId">
<input style="display: none;" type="submit"/> <input style="display: none;" type="submit"/>
<FormGroup> <FormGroup>
<label for="devicesInput">{{ $t('app.resources.devices.label') }} <sup><a href="https://docs.cloudron.io/apps/#devices" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label> <label for="devicesInput">{{ $t('app.resources.devices.label') }} <sup><a href="https://docs.cloudron.io/apps/#devices" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
@@ -152,6 +152,6 @@ onMounted(async () => {
</fieldset> </fieldset>
</form> </form>
<br/> <br/>
<Button @click="onSubmitDevices()" :loading="devicesBusy" :disabled="devicesBusy || (!app.error && !devicesChanged) || (app.error && app.error.details.installationState !== ISTATES.PENDING_RECREATE_CONTAINER) || app.taskId">{{ $t('main.dialog.save') }}</Button> <Button @click="onSubmitDevices()" :loading="devicesBusy" :disabled="devicesBusy || (!app.error && !devicesChanged) || (app.error && app.error.installationState !== ISTATES.PENDING_RECREATE_CONTAINER) || app.taskId">{{ $t('main.dialog.save') }}</Button>
</div> </div>
</template> </template>

View File

@@ -58,7 +58,7 @@ onMounted(() => {
<label>{{ $t('app.turn.title') }} <sup><a href="https://docs.cloudron.io/apps/#turn" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label> <label>{{ $t('app.turn.title') }} <sup><a href="https://docs.cloudron.io/apps/#turn" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
<div>{{ $t('app.turn.info') }}</div> <div>{{ $t('app.turn.info') }}</div>
</div> </div>
<Switch @change="onTurnChange" v-model="turnEnabled" :disabled="turnBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId"/> <Switch @change="onTurnChange" v-model="turnEnabled" :disabled="turnBusy || (app.error && app.error.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId"/>
</SettingsItem> </SettingsItem>
<SettingsItem v-if="hasOptionalRedis"> <SettingsItem v-if="hasOptionalRedis">
@@ -66,7 +66,7 @@ onMounted(() => {
<label>{{ $t('app.redis.title') }} <sup><a href="https://docs.cloudron.io/apps/#redis" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label> <label>{{ $t('app.redis.title') }} <sup><a href="https://docs.cloudron.io/apps/#redis" class="help" target="_blank"><i class="fa fa-question-circle"></i></a></sup></label>
<div>{{ $t('app.redis.info') }}</div> <div>{{ $t('app.redis.info') }}</div>
</div> </div>
<Switch @change="onRedisChange" v-model="redisEnabled" :disabled="redisBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId"/> <Switch @change="onRedisChange" v-model="redisEnabled" :disabled="redisBusy || (app.error && app.error.installationState !== ISTATES.PENDING_SERVICES_CHANGE) || app.taskId"/>
</SettingsItem> </SettingsItem>
</div> </div>
</template> </template>

View File

@@ -165,7 +165,7 @@ onMounted(async () => {
<div description v-html="$t('app.storage.appdata.description', { storagePath: ('/home/yellowtent/appsdata/' + app.id) })"></div> <div description v-html="$t('app.storage.appdata.description', { storagePath: ('/home/yellowtent/appsdata/' + app.id) })"></div>
<form @submit.prevent="onSubmitMove()" autocomplete="off"> <form @submit.prevent="onSubmitMove()" autocomplete="off">
<fieldset :disabled="moveBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_DATA_DIR_MIGRATION) || !!app.taskId"> <fieldset :disabled="moveBusy || (app.error && app.error.installationState !== ISTATES.PENDING_DATA_DIR_MIGRATION) || !!app.taskId">
<input type="submit" style="display: none"/> <input type="submit" style="display: none"/>
<FormGroup> <FormGroup>
@@ -185,7 +185,7 @@ onMounted(async () => {
<div v-if="moveError" class="error-label">{{ moveError }}</div> <div v-if="moveError" class="error-label">{{ moveError }}</div>
<br/> <br/>
<Button @click="onSubmitMove()" :loading="moveBusy" :disabled="moveBusy || (!app.error && originalVolumeId === volumeId) || (app.error && app.error.details.installationState !== ISTATES.PENDING_DATA_DIR_MIGRATION) || !!app.taskId">{{ $t('app.storage.appdata.moveAction') }}</Button> <Button @click="onSubmitMove()" :loading="moveBusy" :disabled="moveBusy || (!app.error && originalVolumeId === volumeId) || (app.error && app.error.installationState !== ISTATES.PENDING_DATA_DIR_MIGRATION) || !!app.taskId">{{ $t('app.storage.appdata.moveAction') }}</Button>
<hr style="margin-top: 20px;"> <hr style="margin-top: 20px;">
@@ -226,7 +226,7 @@ onMounted(async () => {
</FormGroup> </FormGroup>
<br/> <br/>
<Button @click="onSubmitMounts()" :loading="mountsBusy" :disabled="mountsBusy || (app.error && app.error.details.installationState !== ISTATES.PENDING_RECREATE_CONTAINER) || !!app.taskId || (!app.error && !mountsChanged) || !mountsValid">{{ $t('app.storage.mounts.saveAction') }}</Button> <Button @click="onSubmitMounts()" :loading="mountsBusy" :disabled="mountsBusy || (app.error && app.error.installationState !== ISTATES.PENDING_RECREATE_CONTAINER) || !!app.taskId || (!app.error && !mountsChanged) || !mountsValid">{{ $t('app.storage.mounts.saveAction') }}</Button>
</div> </div>
</template> </template>

View File

@@ -146,7 +146,7 @@ onMounted(async () => {
<div class="error-label" style="margin-top: 12px" v-if="app.updateInfo.unstable">{{ $t('app.updateDialog.unstableWarning') }}</div> <div class="error-label" style="margin-top: 12px" v-if="app.updateInfo.unstable">{{ $t('app.updateDialog.unstableWarning') }}</div>
</div> </div>
<br/> <br/>
<Button v-if="app.updateInfo && features.appUpdates" :danger="app.updateInfo.unstable ? true : null" :success="app.updateInfo.unstable ? null : true" @click="onAskUpdate()" :disabled="app.taskId || (app.error && app.error.details.installationState !== ISTATES.PENDING_UPDATE) || app.runState === 'stopped' || app.installationState === 'pending_update'">{{ $t('app.updateDialog.updateAction') }}</Button> <Button v-if="app.updateInfo && features.appUpdates" :danger="app.updateInfo.unstable ? true : null" :success="app.updateInfo.unstable ? null : true" @click="onAskUpdate()" :disabled="app.taskId || (app.error && app.error.installationState !== ISTATES.PENDING_UPDATE) || app.runState === 'stopped' || app.installationState === 'pending_update'">{{ $t('app.updateDialog.updateAction') }}</Button>
<Button v-else-if="app.updateInfo && !features.appUpdates && profile.isAtLeastOwner" success href="/#/cloudron-account">{{ $t('app.updateDialog.setupSubscriptionAction') }}</Button> <Button v-else-if="app.updateInfo && !features.appUpdates && profile.isAtLeastOwner" success href="/#/cloudron-account">{{ $t('app.updateDialog.setupSubscriptionAction') }}</Button>
</div> </div>
</template> </template>

View File

@@ -159,7 +159,7 @@ const TARGET_RUN_STATE = {
function targetRunState() { function targetRunState() {
// if we have an error, we want to retry the pending state, otherwise toggle the runstate // if we have an error, we want to retry the pending state, otherwise toggle the runstate
if (app.value.error) { if (app.value.error) {
if (app.value.error.details.installationState === ISTATES.PENDING_START) return TARGET_RUN_STATE.START; if (app.value.error.installationState === ISTATES.PENDING_START) return TARGET_RUN_STATE.START;
else return TARGET_RUN_STATE.STOP; else return TARGET_RUN_STATE.STOP;
} else { } else {
if (app.value.runState === RSTATES.STOPPED) return TARGET_RUN_STATE.START; if (app.value.runState === RSTATES.STOPPED) return TARGET_RUN_STATE.START;
@@ -213,7 +213,7 @@ function hashChange() {
if (parts.length !== 2) return; if (parts.length !== 2) return;
const newView = parts[1] || 'info'; const newView = parts[1] || 'info';
if (!isViewEnabled(newView, app.value.error?.details.installationState)) { if (!isViewEnabled(newView, app.value.error?.installationState)) {
if (!currentView.value) { if (!currentView.value) {
currentView.value = 'info'; currentView.value = 'info';
window.location.hash = `/app/${id.value}/info`; window.location.hash = `/app/${id.value}/info`;
@@ -245,7 +245,7 @@ onMounted(async () => {
function buildMenuItem(id, label) { function buildMenuItem(id, label) {
return { return {
id: id, id: id,
disabled: () => !isViewEnabled(id, app.value.error?.details.installationState), disabled: () => !isViewEnabled(id, app.value.error?.installationState),
label: label, label: label,
href: `/#/app/${id.value}/${id}`, href: `/#/app/${id.value}/${id}`,
}; };
@@ -323,8 +323,8 @@ onBeforeUnmount(() => {
<div class="configure-body"> <div class="configure-body">
<div class="configure-menu pankow-no-mobile"> <div class="configure-menu pankow-no-mobile">
<div v-for="view in views" :key="view.id" class="configure-menu-item" :active="currentView === view.id ? true : null" :disabled="isViewEnabled(view.id, app.error?.details.installationState) ? null : true"> <div v-for="view in views" :key="view.id" class="configure-menu-item" :active="currentView === view.id ? true : null" :disabled="isViewEnabled(view.id, app.error?.installationState) ? null : true">
<a v-if="isViewEnabled(view.id, app.error?.details.installationState)" :href="`/#/app/${app.id}/${view.id}`">{{ view.label }}</a> <a v-if="isViewEnabled(view.id, app.error?.installationState)" :href="`/#/app/${app.id}/${view.id}`">{{ view.label }}</a>
<span v-else>{{ view.label }}</span> <span v-else>{{ view.label }}</span>
</div> </div>
</div> </div>