Refresh apps with task info if exists
This commit is contained in:
@@ -11,9 +11,13 @@
|
||||
<div v-show="ready">
|
||||
<TransitionGroup name="grid-animation" tag="div" class="grid" v-if="viewType === VIEW_TYPE.GRID">
|
||||
<a v-for="app in filteredApps" :key="app.id" class="grid-item" @click="onOpenApp(app, $event)" :href="'https://' + app.fqdn" target="_blank" v-tooltip="app.fqdn">
|
||||
<a class="config" v-show="isOperator(app)" :href="`#/app/${app.id}/info`" @click="openAppInfo(app)"><Icon icon="fa-solid fa-cog" /></a>
|
||||
<img :src="API_ORIGIN + app.iconUrl"/>
|
||||
<div class="label">{{ app.label || app.subdomain || app.fqdn }}</div>
|
||||
<a class="config" v-show="isOperator(app)" :href="`#/app/${app.id}/info`"><Icon icon="fa-solid fa-cog" /></a>
|
||||
<div class="grid-item-label">{{ app.label || app.subdomain || app.fqdn }}</div>
|
||||
<div class="apps-progress" v-show="isOperator(app)">
|
||||
<div class="apps-progress-filled" :style="{ width: app.progress+'%' }"></div>
|
||||
<div class="apps-progress-label">{{ installationStateLabel(app) }}</div>
|
||||
</div>
|
||||
</a>
|
||||
</TransitionGroup>
|
||||
|
||||
@@ -75,7 +79,7 @@
|
||||
|
||||
<script>
|
||||
|
||||
import { Button, ButtonGroup, Icon, TableView, TextInput } from 'pankow';
|
||||
import { Button, ButtonGroup, Icon, ProgressBar, TableView, TextInput } from 'pankow';
|
||||
|
||||
import { APP_TYPES, HSTATES, ISTATES, RSTATES } from '../constants.js';
|
||||
import AppsModel from '../models/AppsModel.js';
|
||||
@@ -98,6 +102,7 @@ export default {
|
||||
Button,
|
||||
ButtonGroup,
|
||||
Icon,
|
||||
ProgressBar,
|
||||
TableView,
|
||||
TextInput,
|
||||
},
|
||||
@@ -130,9 +135,7 @@ export default {
|
||||
label: 'Login',
|
||||
sort: true
|
||||
},
|
||||
actions: {
|
||||
|
||||
}
|
||||
actions: {}
|
||||
}
|
||||
};
|
||||
},
|
||||
@@ -144,14 +147,18 @@ export default {
|
||||
}
|
||||
},
|
||||
methods: {
|
||||
installationStateLabel: AppsModel.installationStateLabel,
|
||||
installationActive: AppsModel.installationActive,
|
||||
appProgressMessage: AppsModel.appProgressMessage,
|
||||
openAppInfo(app) {
|
||||
window.location.href = `#/app/${app.id}/info`;
|
||||
},
|
||||
onOpenApp(app, event) {
|
||||
function stopEvent() {
|
||||
event.stopPropagation();
|
||||
// event.preventDefault();
|
||||
event.preventDefault();
|
||||
}
|
||||
|
||||
console.log(event)
|
||||
|
||||
if (app.installationState !== ISTATES.INSTALLED) {
|
||||
if (app.installationState === ISTATES.ERROR && this.isOperator(app)) window.location.href = `#/app/${app.id}/repair`;
|
||||
return stopEvent();
|
||||
@@ -166,7 +173,6 @@ export default {
|
||||
return stopEvent();
|
||||
}
|
||||
|
||||
|
||||
// if (app.pendingPostInstallConfirmation && $scope.appPostInstallConfirm) {
|
||||
// $scope.appPostInstallConfirm.show(app);
|
||||
// return stopEvent();
|
||||
@@ -219,6 +225,34 @@ export default {
|
||||
height: 32px;
|
||||
}
|
||||
|
||||
.apps-progress {
|
||||
position: relative;
|
||||
width: 90%;
|
||||
text-align: center;
|
||||
border-radius: 10px;
|
||||
color: var(--pankow-text-color);
|
||||
}
|
||||
|
||||
.apps-progress-filled {
|
||||
background-color: var(--pankow-color-primary);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
left: 0;
|
||||
height: 100%;
|
||||
border-radius: 10px;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.apps-progress-label {
|
||||
position: relative;
|
||||
z-index: 2;
|
||||
opacity: 0.7;
|
||||
font-size: 12px;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
.actions {
|
||||
text-align: right;
|
||||
visibility: hidden;
|
||||
@@ -264,15 +298,15 @@ tr:hover .actions {
|
||||
height: 80px;
|
||||
}
|
||||
|
||||
.label {
|
||||
.grid-item-label {
|
||||
font-size: 18px;
|
||||
font-weight: 100;
|
||||
margin: 10px;
|
||||
margin: 5px 0 5px 0;
|
||||
color: var(--pankow-text-color);
|
||||
}
|
||||
|
||||
.grid-item:focus .label,
|
||||
.grid-item:hover .label {
|
||||
.grid-item:focus .grid-item-label,
|
||||
.grid-item:hover .grid-item-label {
|
||||
text-decoration: none;
|
||||
color: var(--accent-color);;
|
||||
}
|
||||
|
||||
@@ -1,11 +1,89 @@
|
||||
|
||||
import { ISTATES } from '../constants.js';
|
||||
import { APP_TYPES, HSTATES, ISTATES, RSTATES } from '../constants.js';
|
||||
import { fetcher } from 'pankow';
|
||||
import { sleep } from 'pankow/utils';
|
||||
import moment from 'moment';
|
||||
|
||||
function installationStateLabel(app) {
|
||||
if (!app) return '';
|
||||
|
||||
const waiting = app.progress === 0 ? ' (Queued)' : '';
|
||||
|
||||
switch (app.installationState) {
|
||||
case ISTATES.PENDING_INSTALL:
|
||||
return 'Installing' + waiting;
|
||||
case ISTATES.PENDING_CLONE:
|
||||
return 'Cloning' + waiting;
|
||||
case ISTATES.PENDING_LOCATION_CHANGE:
|
||||
case ISTATES.PENDING_CONFIGURE:
|
||||
case ISTATES.PENDING_RECREATE_CONTAINER:
|
||||
case ISTATES.PENDING_SERVICES_CHANGE:
|
||||
case ISTATES.PENDING_DEBUG:
|
||||
return 'Configuring' + waiting;
|
||||
case ISTATES.PENDING_RESIZE:
|
||||
return 'Resizing' + waiting;
|
||||
case ISTATES.PENDING_DATA_DIR_MIGRATION:
|
||||
return 'Migrating data' + waiting;
|
||||
case ISTATES.PENDING_UNINSTALL: return 'Uninstalling' + waiting;
|
||||
case ISTATES.PENDING_RESTORE: return 'Restoring' + waiting;
|
||||
case ISTATES.PENDING_IMPORT: return 'Importing' + waiting;
|
||||
case ISTATES.PENDING_UPDATE: return 'Updating' + waiting;
|
||||
case ISTATES.PENDING_BACKUP: return 'Backing up' + waiting;
|
||||
case ISTATES.PENDING_START: return 'Starting' + waiting;
|
||||
case ISTATES.PENDING_STOP: return 'Stopping' + waiting;
|
||||
case ISTATES.PENDING_RESTART: return 'Restarting' + waiting;
|
||||
case ISTATES.ERROR: {
|
||||
if (app.error && app.error.message === 'ETRYAGAIN') return 'DNS Error';
|
||||
return 'Error';
|
||||
}
|
||||
case ISTATES.INSTALLED: {
|
||||
if (app.debugMode) {
|
||||
return 'Recovery Mode';
|
||||
} else if (app.runState === RSTATES.RUNNING) {
|
||||
if (!app.health) return 'Starting...'; // no data yet
|
||||
if (app.type === APP_TYPES.LINK) return '';
|
||||
if (app.health === HSTATES.HEALTHY) return 'Running';
|
||||
return 'Not responding'; // dead/exit/unhealthy
|
||||
} else if (app.runState === RSTATES.STOPPED) {
|
||||
return 'Stopped';
|
||||
} else {
|
||||
return app.runState;
|
||||
}
|
||||
}
|
||||
default: return app.installationState;
|
||||
}
|
||||
}
|
||||
|
||||
function installationActive(app) {
|
||||
if (app.installationState === ISTATES.ERROR) return false;
|
||||
if (app.installationState === ISTATES.INSTALLED) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
function appProgressMessage(app) {
|
||||
return app.message || (app.error ? app.error.message : '');
|
||||
}
|
||||
|
||||
function create(origin, accessToken, id) {
|
||||
async function getTask(appId) {
|
||||
let error, result;
|
||||
try {
|
||||
result = await fetcher.get(`${origin}/api/v1/apps/${appId}/task`, { access_token: accessToken });
|
||||
} catch (e) {
|
||||
error = e;
|
||||
}
|
||||
|
||||
if (error || result.status !== 200) {
|
||||
console.error('Failed to get task for app.', error || result.status);
|
||||
return null;
|
||||
}
|
||||
|
||||
return result.body;
|
||||
}
|
||||
|
||||
export function create(origin, accessToken, id) {
|
||||
return {
|
||||
name: 'AppsModel',
|
||||
getTask,
|
||||
async list() {
|
||||
let error, result;
|
||||
try {
|
||||
@@ -19,6 +97,30 @@ export function create(origin, accessToken, id) {
|
||||
return [];
|
||||
}
|
||||
|
||||
for (const app of result.body.apps) {
|
||||
app.ssoAuth = app.sso && (app.manifest.addons['ldap'] || app.manifest.addons['oidc'] || app.manifest.addons['proxyAuth']); // checking app.sso first ensures app.manifest.addons is not null
|
||||
|
||||
if (app.accessLevel !== 'operator' && app.accessLevel !== 'admin') { // only fetch if we have permissions
|
||||
app.progress = 0;
|
||||
app.message = '';
|
||||
app.taskMinutesActive = 0;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!app.taskId) continue;
|
||||
|
||||
const task = await getTask(app.id);
|
||||
if (task) {
|
||||
app.progress = task.percent;
|
||||
app.message = task.message;
|
||||
app.taskMinutesActive = moment.duration(moment.utc().diff(moment.utc(task.creationTime))).asMinutes();
|
||||
} else {
|
||||
app.progress = 0;
|
||||
app.message = '';
|
||||
app.taskMinutesActive = 0;
|
||||
}
|
||||
}
|
||||
|
||||
return result.body.apps;
|
||||
},
|
||||
async get() {
|
||||
@@ -67,5 +169,8 @@ export function create(origin, accessToken, id) {
|
||||
}
|
||||
|
||||
export default {
|
||||
create
|
||||
create,
|
||||
installationStateLabel,
|
||||
installationActive,
|
||||
appProgressMessage,
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user