mirror of
https://github.com/YunoHost/yunohost-admin.git
synced 2024-09-03 20:06:15 +02:00
add LazyRenderer component & update AppCatalog
This commit is contained in:
parent
9b3ac1fcaf
commit
c7d8f5fb68
2 changed files with 124 additions and 44 deletions
59
app/src/components/LazyRenderer.vue
Normal file
59
app/src/components/LazyRenderer.vue
Normal file
|
@ -0,0 +1,59 @@
|
||||||
|
<template>
|
||||||
|
<div class="lazy-renderer" :style="`min-height: ${fixedMinHeight}px`">
|
||||||
|
<slot v-if="render" />
|
||||||
|
</div>
|
||||||
|
</template>
|
||||||
|
|
||||||
|
<script>
|
||||||
|
export default {
|
||||||
|
name: 'LazyRenderer',
|
||||||
|
|
||||||
|
props: {
|
||||||
|
unrender: { type: Boolean, default: true },
|
||||||
|
minHeight: { type: Number, default: 0 },
|
||||||
|
renderDelay: { type: Number, default: 100 },
|
||||||
|
unrenderDelay: { type: Number, default: 2000 },
|
||||||
|
rootMargin: { type: String, default: '300px' }
|
||||||
|
},
|
||||||
|
|
||||||
|
data () {
|
||||||
|
return {
|
||||||
|
observer: null,
|
||||||
|
render: false,
|
||||||
|
fixedMinHeight: this.minHeight
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
mounted () {
|
||||||
|
let unrenderTimer
|
||||||
|
let renderTimer
|
||||||
|
this.observer = new IntersectionObserver(entries => {
|
||||||
|
if (entries[0].isIntersecting) {
|
||||||
|
clearTimeout(unrenderTimer)
|
||||||
|
// Show the component after a delay (to avoid rendering while scrolling fast)
|
||||||
|
renderTimer = setTimeout(() => {
|
||||||
|
this.render = true
|
||||||
|
}, this.unrender ? this.renderDelay : 0)
|
||||||
|
|
||||||
|
if (!this.unrender) {
|
||||||
|
// Stop listening to intersections after first appearance if unrendering is not activated
|
||||||
|
this.observer.disconnect()
|
||||||
|
}
|
||||||
|
} else if (this.unrender) {
|
||||||
|
clearTimeout(renderTimer)
|
||||||
|
// Hide the component after a delay if it's no longer in the viewport
|
||||||
|
unrenderTimer = setTimeout(() => {
|
||||||
|
this.fixedMinHeight = this.$el.clientHeight
|
||||||
|
this.render = false
|
||||||
|
}, this.unrenderDelay)
|
||||||
|
}
|
||||||
|
}, { rootMargin: this.rootMargin })
|
||||||
|
|
||||||
|
this.observer.observe(this.$el)
|
||||||
|
},
|
||||||
|
|
||||||
|
beforeDestroy () {
|
||||||
|
this.observer.disconnect()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
|
@ -64,52 +64,56 @@
|
||||||
|
|
||||||
<!-- APPS CARDS -->
|
<!-- APPS CARDS -->
|
||||||
<b-card-group v-else deck>
|
<b-card-group v-else deck>
|
||||||
<b-card no-body v-for="app in filteredApps" :key="app.id">
|
<lazy-renderer v-for="app in filteredApps" :key="app.id" :min-height="120">
|
||||||
<b-card-body class="d-flex flex-column">
|
<b-card no-body>
|
||||||
<b-card-title class="d-flex mb-2">
|
<b-card-body class="d-flex flex-column">
|
||||||
{{ app.manifest.name }}
|
<b-card-title class="d-flex mb-2">
|
||||||
<small v-if="app.state !== 'working'" class="d-flex align-items-center ml-2">
|
{{ app.manifest.name }}
|
||||||
<b-badge
|
|
||||||
v-if="app.state !== 'highquality'"
|
|
||||||
:variant="(app.color === 'danger' && app.state === 'lowquality') ? 'warning' : app.color"
|
|
||||||
v-b-popover.hover.bottom="$t(`app_state_${app.state}_explanation`)"
|
|
||||||
>
|
|
||||||
{{ $t('app_state_' + app.state) }}
|
|
||||||
</b-badge>
|
|
||||||
<icon
|
|
||||||
v-else iname="star" class="star"
|
|
||||||
v-b-popover.hover.bottom="$t(`app_state_${app.state}_explanation`)"
|
|
||||||
/>
|
|
||||||
</small>
|
|
||||||
</b-card-title>
|
|
||||||
|
|
||||||
<b-card-text>{{ app.manifest.description }}</b-card-text>
|
<small v-if="app.state !== 'working'" class="d-flex align-items-center ml-2">
|
||||||
|
<b-badge
|
||||||
|
v-if="app.state !== 'highquality'"
|
||||||
|
:variant="(app.color === 'danger' && app.state === 'lowquality') ? 'warning' : app.color"
|
||||||
|
v-b-popover.hover.bottom="$t(`app_state_${app.state}_explanation`)"
|
||||||
|
>
|
||||||
|
{{ $t('app_state_' + app.state) }}
|
||||||
|
</b-badge>
|
||||||
|
|
||||||
<b-card-text v-if="app.maintained === 'orphaned'" class="align-self-end mt-auto">
|
<icon
|
||||||
<span class="alert-warning p-1" v-b-popover.hover.top="$t('orphaned_details')">
|
v-else iname="star" class="star"
|
||||||
<icon iname="warning" /> {{ $t(app.maintained) }}
|
v-b-popover.hover.bottom="$t(`app_state_${app.state}_explanation`)"
|
||||||
</span>
|
/>
|
||||||
</b-card-text>
|
</small>
|
||||||
</b-card-body>
|
</b-card-title>
|
||||||
|
|
||||||
<!-- APP BUTTONS -->
|
<b-card-text>{{ app.manifest.description }}</b-card-text>
|
||||||
<b-button-group>
|
|
||||||
<b-button :href="app.git.url" variant="outline-dark" target="_blank">
|
|
||||||
<icon iname="code" /> {{ $t('code') }}
|
|
||||||
</b-button>
|
|
||||||
|
|
||||||
<b-button :href="app.git.url + '/blob/master/README.md'" variant="outline-dark" target="_blank">
|
<b-card-text v-if="app.maintained === 'orphaned'" class="align-self-end mt-auto">
|
||||||
<icon iname="book" /> {{ $t('readme') }}
|
<span class="alert-warning p-1" v-b-popover.hover.top="$t('orphaned_details')">
|
||||||
</b-button>
|
<icon iname="warning" /> {{ $t(app.maintained) }}
|
||||||
|
</span>
|
||||||
|
</b-card-text>
|
||||||
|
</b-card-body>
|
||||||
|
|
||||||
<b-button v-if="app.isInstallable" :variant="app.color" @click="onInstallClick(app)">
|
<!-- APP BUTTONS -->
|
||||||
<icon iname="plus" /> {{ $t('install') }} <icon v-if="app.color === 'danger'" class="ml-1" iname="warning" />
|
<b-button-group>
|
||||||
</b-button>
|
<b-button :href="app.git.url" variant="outline-dark" target="_blank">
|
||||||
<b-button v-else :variant="app.color" disabled>
|
<icon iname="code" /> {{ $t('code') }}
|
||||||
{{ $t('installed') }}
|
</b-button>
|
||||||
</b-button>
|
|
||||||
</b-button-group>
|
<b-button :href="app.git.url + '/blob/master/README.md'" variant="outline-dark" target="_blank">
|
||||||
</b-card>
|
<icon iname="book" /> {{ $t('readme') }}
|
||||||
|
</b-button>
|
||||||
|
|
||||||
|
<b-button v-if="app.isInstallable" :variant="app.color" @click="onInstallClick(app)">
|
||||||
|
<icon iname="plus" /> {{ $t('install') }} <icon v-if="app.color === 'danger'" class="ml-1" iname="warning" />
|
||||||
|
</b-button>
|
||||||
|
<b-button v-else :variant="app.color" disabled>
|
||||||
|
{{ $t('installed') }}
|
||||||
|
</b-button>
|
||||||
|
</b-button-group>
|
||||||
|
</b-card>
|
||||||
|
</lazy-renderer>
|
||||||
</b-card-group>
|
</b-card-group>
|
||||||
|
|
||||||
<template #bot>
|
<template #bot>
|
||||||
|
@ -155,12 +159,17 @@
|
||||||
<script>
|
<script>
|
||||||
import { validationMixin } from 'vuelidate'
|
import { validationMixin } from 'vuelidate'
|
||||||
|
|
||||||
|
import LazyRenderer from '@/components/LazyRenderer'
|
||||||
import { required, githubLink } from '@/helpers/validators'
|
import { required, githubLink } from '@/helpers/validators'
|
||||||
import { randint } from '@/helpers/commons'
|
import { randint } from '@/helpers/commons'
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
name: 'AppCatalog',
|
name: 'AppCatalog',
|
||||||
|
|
||||||
|
components: {
|
||||||
|
LazyRenderer
|
||||||
|
},
|
||||||
|
|
||||||
data () {
|
data () {
|
||||||
return {
|
return {
|
||||||
queries: [
|
queries: [
|
||||||
|
@ -375,10 +384,11 @@ export default {
|
||||||
}
|
}
|
||||||
|
|
||||||
.card-deck {
|
.card-deck {
|
||||||
.card {
|
> * {
|
||||||
border-color: $gray-400;
|
margin-left: 15px;
|
||||||
|
margin-right: 15px;
|
||||||
margin-bottom: 2rem;
|
margin-bottom: 2rem;
|
||||||
flex-basis: 90%;
|
flex-basis: 100%;
|
||||||
@include media-breakpoint-up(md) {
|
@include media-breakpoint-up(md) {
|
||||||
flex-basis: 50%;
|
flex-basis: 50%;
|
||||||
max-width: calc(50% - 30px);
|
max-width: calc(50% - 30px);
|
||||||
|
@ -388,6 +398,15 @@ export default {
|
||||||
max-width: calc(33.3% - 30px);
|
max-width: calc(33.3% - 30px);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
margin: 0;
|
||||||
|
height: 100%;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.card {
|
||||||
|
border-color: $gray-400;
|
||||||
|
|
||||||
// not maintained info
|
// not maintained info
|
||||||
.alert-warning {
|
.alert-warning {
|
||||||
font-size: .75em;
|
font-size: .75em;
|
||||||
|
@ -402,6 +421,8 @@ export default {
|
||||||
@include media-breakpoint-up(sm) {
|
@include media-breakpoint-up(sm) {
|
||||||
min-height: 10rem;
|
min-height: 10rem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
flex-basis: 90%;
|
||||||
border: 0;
|
border: 0;
|
||||||
|
|
||||||
.btn {
|
.btn {
|
||||||
|
|
Loading…
Add table
Reference in a new issue