2024-12-29 00:36:48 +01:00
|
|
|
<template>
|
|
|
|
|
<div class="content">
|
2024-12-29 19:19:03 +01:00
|
|
|
<h1 class="section-header">
|
|
|
|
|
{{ $t('apps.title') }}
|
|
|
|
|
<TextInput v-model="filter" placeholder="Filter ..." />
|
|
|
|
|
</h1>
|
2024-12-29 00:36:48 +01:00
|
|
|
|
2024-12-29 19:19:03 +01:00
|
|
|
<TransitionGroup name="grid-animation" tag="div" class="grid">
|
|
|
|
|
<a v-for="app in filteredApps" :key="app.id" class="item" :href="'https://' + app.fqdn" target="_blank" v-tooltip="app.fqdn">
|
2024-12-29 00:36:48 +01:00
|
|
|
<img :src="API_ORIGIN + app.iconUrl"/>
|
|
|
|
|
<div class="label">{{ app.label || app.subdomain || app.fqdn }}</div>
|
|
|
|
|
<a class="config" :href="`#/app/${app.id}/info`"><Icon icon="fa-solid fa-cog" /></a>
|
|
|
|
|
</a>
|
2024-12-29 19:19:03 +01:00
|
|
|
</TransitionGroup>
|
2024-12-29 19:25:35 +01:00
|
|
|
|
|
|
|
|
<!-- TODO check user permissions -->
|
|
|
|
|
<div class="empty-placeholder" v-if="filteredApps.length === 0">
|
|
|
|
|
<!-- for admins -->
|
|
|
|
|
<div v-if="false">
|
|
|
|
|
<h4><i class="fa fa-cloud-download fa-fw"></i> {{ $t('apps.noApps.title') }}</h4>
|
|
|
|
|
<h5 v-html="$t('apps.noApps.description', { appStoreLink: '#/appstore' })"></h5>
|
|
|
|
|
</div>
|
|
|
|
|
|
|
|
|
|
<!-- for non-admins -->
|
|
|
|
|
<div v-if="true">
|
|
|
|
|
<h4>{{ $t('apps.noAccess.title') }}</h4>
|
|
|
|
|
<h5>{{ $t('apps.noAccess.description') }}</h5>
|
|
|
|
|
</div>
|
|
|
|
|
</div>
|
2024-12-29 00:36:48 +01:00
|
|
|
</div>
|
|
|
|
|
</template>
|
|
|
|
|
|
|
|
|
|
<script>
|
|
|
|
|
|
2024-12-29 19:19:03 +01:00
|
|
|
import { Button, Icon, TextInput } from 'pankow';
|
2024-12-29 00:36:48 +01:00
|
|
|
|
|
|
|
|
import AppsModel from '../models/AppsModel.js';
|
|
|
|
|
|
|
|
|
|
const API_ORIGIN = import.meta.env.VITE_API_ORIGIN ? import.meta.env.VITE_API_ORIGIN : window.location.origin;
|
|
|
|
|
const accessToken = localStorage.token;
|
|
|
|
|
|
|
|
|
|
const appsModel = AppsModel.create(API_ORIGIN, accessToken);
|
|
|
|
|
|
|
|
|
|
export default {
|
|
|
|
|
name: 'AppsView',
|
|
|
|
|
components: {
|
|
|
|
|
Button,
|
|
|
|
|
Icon,
|
2024-12-29 19:19:03 +01:00
|
|
|
TextInput,
|
2024-12-29 00:36:48 +01:00
|
|
|
},
|
|
|
|
|
data() {
|
|
|
|
|
return {
|
|
|
|
|
API_ORIGIN,
|
|
|
|
|
ready: false,
|
2024-12-29 19:19:03 +01:00
|
|
|
filter: '',
|
2024-12-29 00:36:48 +01:00
|
|
|
apps: [],
|
|
|
|
|
};
|
|
|
|
|
},
|
2024-12-29 19:19:03 +01:00
|
|
|
computed: {
|
|
|
|
|
filteredApps() {
|
|
|
|
|
return this.apps.filter(a => {
|
|
|
|
|
return a.fqdn.indexOf(this.filter) !== -1;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
},
|
2024-12-29 00:36:48 +01:00
|
|
|
methods: {
|
|
|
|
|
},
|
|
|
|
|
async mounted() {
|
|
|
|
|
this.apps = await appsModel.list();
|
|
|
|
|
console.log(this.apps)
|
|
|
|
|
this.ready = true;
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
</script>
|
|
|
|
|
|
|
|
|
|
<style scoped>
|
|
|
|
|
|
2024-12-29 19:19:03 +01:00
|
|
|
.grid-animation-enter-active,
|
|
|
|
|
.grid-animation-leave-active {
|
|
|
|
|
transition: all 0.2s ease;
|
|
|
|
|
}
|
|
|
|
|
.grid-animation-enter-from,
|
|
|
|
|
.grid-animation-leave-to {
|
|
|
|
|
opacity: 0;
|
|
|
|
|
transform: translateX(30px);
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-29 00:36:48 +01:00
|
|
|
.grid {
|
|
|
|
|
display: flex;
|
|
|
|
|
height: 100%;
|
|
|
|
|
width: 100%;
|
|
|
|
|
transition: 300ms;
|
|
|
|
|
flex-wrap: wrap;
|
|
|
|
|
justify-content: start;
|
|
|
|
|
align-content: start;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item {
|
|
|
|
|
position: relative;
|
|
|
|
|
display: flex;
|
|
|
|
|
flex-direction: column;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
width: 190px;
|
|
|
|
|
height: 180px;
|
|
|
|
|
margin: 10px;
|
|
|
|
|
overflow: hidden;
|
|
|
|
|
border-radius: 10px;
|
|
|
|
|
background-color: var(--card-background);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item:focus,
|
|
|
|
|
.item:hover {
|
|
|
|
|
box-shadow: 0px 2px 5px rgba(0, 0, 0, 0.1);
|
|
|
|
|
background-color: var(--pankow-color-background-hover);
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item img {
|
|
|
|
|
width: 80px;
|
|
|
|
|
height: 80px;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.label {
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
font-weight: 100;
|
|
|
|
|
margin: 10px;
|
|
|
|
|
color: var(--pankow-text-color);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item:focus .label,
|
|
|
|
|
.item:hover .label {
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
color: var(--accent-color);;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.config {
|
|
|
|
|
position: absolute;
|
|
|
|
|
color: var(--pankow-text-color);
|
|
|
|
|
font-size: 18px;
|
|
|
|
|
cursor: pointer;
|
|
|
|
|
width: 50px;
|
|
|
|
|
height: 50px;
|
|
|
|
|
border-top-right-radius: 10px;
|
|
|
|
|
right: 0;
|
|
|
|
|
top: 0;
|
|
|
|
|
opacity: 0;
|
|
|
|
|
display: flex;
|
|
|
|
|
justify-content: center;
|
|
|
|
|
align-items: center;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.config:focus,
|
|
|
|
|
.config:hover {
|
|
|
|
|
text-decoration: none;
|
|
|
|
|
color: var(--accent-color);;
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
.item:focus .config,
|
|
|
|
|
.item:hover .config {
|
|
|
|
|
opacity: 1;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-29 19:25:35 +01:00
|
|
|
.empty-placeholder {
|
|
|
|
|
margin-top: 20px;
|
|
|
|
|
}
|
|
|
|
|
|
2024-12-29 00:36:48 +01:00
|
|
|
</style>
|