🚧 Refactor + more widgets
* ♻️ segment into smaller widgets, improve mixin * ♻️ change NextcloudInfo to NextcloudUser * a small widget showing branding and uesr info, including quota * ✨ add NextcloudNotifications widget * show and delete Nextcloud notifications * ✨ add NextcloudUserStatus widget * display user statuses of selected users * ✨ add NextcloudStats widget (admin only) * display Nextcloud usage statistics (users, files, shares) * ✨ add NextcloudSystem widget (admin only) * visualise cpu load and memory utilisation, show server versions * ✨ add NextcloudPhpOpcache widget (admin only) * show statistics about php opcache performance * ✨ add a misc helper for formatting nunbers * 🌐 add translations to widget templates * 🌐 add translation entries for en * 🍱 add scss styles file, shared by all widgets
This commit is contained in:
193
src/components/Widgets/NextcloudUser.vue
Normal file
193
src/components/Widgets/NextcloudUser.vue
Normal file
@@ -0,0 +1,193 @@
|
||||
<template>
|
||||
<div v-if="user.id" class="nextcloud-widget nextcloud-info-wrapper">
|
||||
<!-- logo, branding, user info -->
|
||||
<div>
|
||||
<div class="logo">
|
||||
<a :href="branding.url" target="_blank">
|
||||
<img :src="branding.logo" />
|
||||
</a>
|
||||
<p>{{ branding.slogan }}</p>
|
||||
</div>
|
||||
<div class="info">
|
||||
<p class="brand">{{ branding.name }}</p>
|
||||
<p class="version" v-if="version.string">
|
||||
<small>Nextcloud {{ tt('version') }} {{ version.string }}</small>
|
||||
</p>
|
||||
<p class="username">{{ user.displayName }} <em v-if="user.id">({{ user.id }})</em></p>
|
||||
<p class="login" v-tooltip="lastLoginTooltip()">
|
||||
<span>{{ tt('last-login') }}</span>
|
||||
<small>{{ getTimeAgo(user.lastLogin) }}</small>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- disk space/quota -->
|
||||
<div>
|
||||
<div v-tooltip="quotaTooltip()">
|
||||
<hr/>
|
||||
<p>
|
||||
<i class="fal fa-disc-drive"></i>
|
||||
<strong v-if="user.quota.quota > 0">{{ tt('disk-quota') }}</strong>
|
||||
<strong v-else>{{ tt('disk-space') }}</strong>
|
||||
<em v-html="formatPercent(user.quota.relative)"></em>
|
||||
<small>{{ tt('of') }}</small><strong v-html="convertBytes(user.quota.total)"></strong>
|
||||
<span v-if="quotaChartData">
|
||||
<PercentageChart :values="quotaChartData" :showLegend="false" />
|
||||
</span>
|
||||
</p>
|
||||
<hr/>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import NextcloudMixin from '@/mixins/NextcloudMixin';
|
||||
import PercentageChart from '@/components/Charts/PercentageChart';
|
||||
import { convertBytes } from '@/utils/MiscHelpers';
|
||||
// //import { NcdUsr } from '@/utils/ncd';
|
||||
|
||||
/**
|
||||
* NextcloudUser widget - Displays branding and user information
|
||||
* Used endpoints
|
||||
* - capabilities: this delivers branding info (server name, logo, slogan, etc.)
|
||||
* - user: name, last login, disk quota info
|
||||
*/
|
||||
export default {
|
||||
mixins: [WidgetMixin, NextcloudMixin],
|
||||
components: { PercentageChart },
|
||||
data() {
|
||||
return {
|
||||
user: {
|
||||
id: null,
|
||||
displayName: null,
|
||||
email: null,
|
||||
quota: {
|
||||
relative: null,
|
||||
total: null,
|
||||
used: null,
|
||||
free: null,
|
||||
quota: null,
|
||||
},
|
||||
},
|
||||
quotaChartData: null,
|
||||
};
|
||||
},
|
||||
methods: {
|
||||
allowedStatuscodes() {
|
||||
return [100, 200];
|
||||
},
|
||||
fetchData() {
|
||||
if (!this.hasValidCredentials()) return;
|
||||
this.loadCapabilities()
|
||||
.then(this.loadUser)
|
||||
.finally(this.finishLoading);
|
||||
},
|
||||
loadUser() {
|
||||
return this.makeRequest(this.endpoint('user'), this.headers)
|
||||
// //return Promise.resolve(NcdUsr)
|
||||
.then(this.processUser);
|
||||
},
|
||||
processUser(userResponse) {
|
||||
const user = this.validateResponse(userResponse);
|
||||
this.user.id = user.id;
|
||||
this.user.email = user.email;
|
||||
this.user.quota = user.quota;
|
||||
this.user.displayName = user.displayname;
|
||||
this.user.lastLogin = user.lastLogin;
|
||||
const used = parseFloat(this.user.quota.used / this.user.quota.total);
|
||||
const free = parseFloat(this.user.quota.free / this.user.quota.total);
|
||||
this.quotaChartData = [
|
||||
{ label: this.tt('used'), size: used, color: this.getQuotaChartColor(used) },
|
||||
{ label: this.tt('available'), size: free, color: '#20e253' },
|
||||
];
|
||||
},
|
||||
getQuotaChartColor(percent) {
|
||||
if (percent < 0.75) return '#272f4d';
|
||||
if (percent < 0.85) return '#fce216';
|
||||
if (percent < 0.95) return '#ff9000';
|
||||
return '#f80363';
|
||||
},
|
||||
/* Tooltip generators */
|
||||
quotaTooltip() {
|
||||
const quotaEnabled = this.user.quota.quota > 0;
|
||||
const content = `${this.tt('quota-enabled', { not: quotaEnabled ? '' : 'not ' })}`
|
||||
+ `<br><br>${convertBytes(this.user.quota.used)} ${this.tt('used')}<br>`
|
||||
+ `${convertBytes(this.user.quota.free)} ${this.tt('free')}<br>`
|
||||
+ `${convertBytes(this.user.quota.total)} ${this.tt('total')}`;
|
||||
return {
|
||||
content, html: true, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
|
||||
};
|
||||
},
|
||||
lastLoginTooltip() {
|
||||
const content = new Date(this.user.lastLogin).toLocaleString();
|
||||
return {
|
||||
content, html: true, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
|
||||
};
|
||||
},
|
||||
},
|
||||
created() {
|
||||
this.overrideUpdateInterval = 120;
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
@import '@/styles/widgets/nextcloud-shared.scss';
|
||||
.nextcloud-info-wrapper {
|
||||
> div:first-child {
|
||||
display: flex;
|
||||
}
|
||||
> div:nth-child(2) {
|
||||
border-top: none;
|
||||
}
|
||||
div.percentage-chart-wrapper {
|
||||
margin: 0 0.75rem;
|
||||
width: 5em;
|
||||
position: relative;
|
||||
top: 0.2rem;
|
||||
float: right;
|
||||
}
|
||||
div.logo {
|
||||
width: 40%;
|
||||
text-align: center;
|
||||
img {
|
||||
width: 8rem;
|
||||
}
|
||||
p {
|
||||
font-size: 90%;
|
||||
opacity: .85;
|
||||
}
|
||||
}
|
||||
div.info {
|
||||
width: 56%;
|
||||
p {
|
||||
margin: 0 0 1rem 0;
|
||||
}
|
||||
p:last-child {
|
||||
margin: 0;
|
||||
}
|
||||
p.brand {
|
||||
margin: 0;
|
||||
font-size: 135%;
|
||||
font-weight: 800;
|
||||
letter-spacing: 3px;
|
||||
}
|
||||
p.version small {
|
||||
font-size: 75%;
|
||||
}
|
||||
p.username {
|
||||
font-size: 110%;
|
||||
em {
|
||||
font-size: 90%;
|
||||
}
|
||||
}
|
||||
p.login {
|
||||
span {
|
||||
font-size: 90%;
|
||||
margin-right: .25rem;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
Reference in New Issue
Block a user