🚧 Move user processing from widget to mixin

plus
* some template and style tweaking
* improve tooltips
* enforce Nextcloud app-password instead of login password
This commit is contained in:
Marcell Fülöp 2022-06-12 12:33:56 +00:00
parent caf131df23
commit a43988f3cd
2 changed files with 80 additions and 70 deletions

View File

@ -11,11 +11,11 @@
<div class="info">
<p class="brand">{{ branding.name }}</p>
<p class="version" v-if="version.string">
{{ $t('widgets.nextcloud-info.label-version') }} {{ version.string }}
<small>{{ $t('widgets.nextcloud-info.label-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()">
{{ $t('widgets.nextcloud-info.label-last-login') }}&nbsp;
<span>{{ $t('widgets.nextcloud-info.label-last-login') }}</span>&nbsp;
<small>{{ getTimeAgo(user.lastLogin) }}</small>
</p>
</div>
@ -76,10 +76,10 @@
<p v-tooltip="sharesTooltip()">
<i class="fal fa-share"></i>
<em>{{ formatNumber(server.nextcloud.shares.num_shares) }}</em>
<strong>{{ $t('shares') }}</strong> <small> {{ $t('and') }}</small>
<strong>{{ $t('autonomous') }}</strong> <small> {{ $t('and') }}</small>
<em>
{{ formatNumber(server.nextcloud.shares.num_fed_shares_sent) }}
/ {{ formatNumber(server.nextcloud.shares.num_fed_shares_received) }}
{{ formatNumber(server.nextcloud.shares.num_fed_shares_sent +
server.nextcloud.shares.num_fed_shares_received) }}
</em>
<strong>{{ $t('federated shares') }}</strong>
</p>
@ -109,7 +109,7 @@
import WidgetMixin from '@/mixins/WidgetMixin';
import NextcloudMixin from '@/mixins/NextcloudMixin';
import { convertBytes } from '@/utils/MiscHelpers';
// //import { NcdUsr, NcdServer } from '@/utils/ncd';
// //import { NcdServer } from '@/utils/ncd';
const NextcloudSchema = {
branding: {
@ -122,19 +122,6 @@ const NextcloudSchema = {
string: null,
edition: null,
},
user: {
id: null,
isAdmin: false,
displayName: null,
email: null,
quota: {
relative: null,
total: null,
used: null,
free: null,
quota: null,
},
},
server: {
server: {
webserver: null,
@ -213,33 +200,15 @@ export default {
},
methods: {
async fetchData() {
const promise = this.fetchCapabilities()
.then(() => this.makeRequest(this.endpoint('user'), this.headers))
// //.then(() => NcdUsr)
.then(this.processUser);
await promise;
await this.loadCapabilities();
await this.loadUser();
if (this.user.isAdmin) {
promise.then(() => this.makeRequest(this.endpoint('serverinfo'), this.headers))
// //promise.then(() => NcdServer)
.then(this.processServerInfo);
this.processServerInfo(
await this.makeRequest(this.endpoint('serverinfo'), this.headers),
// //NcdServer,
);
}
promise.finally(() => this.finishLoading());
},
processUser(userData) {
const user = userData?.ocs?.data;
if (!user) {
this.error('Invalid response');
return;
}
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;
this.user.isAdmin = user.groups && user.groups.includes('admin');
this.finishLoading();
},
processServerInfo(serverData) {
const data = serverData?.ocs?.data;
@ -278,10 +247,10 @@ export default {
};
},
appUpdatesTooltip() {
const content = 'Updates are available for: '
+ ` ${Object.keys(this.server.nextcloud.system.apps.app_updates).join(', ')}`;
const content = 'Updates are available for:<br><br>'
+ ` ${Object.entries(this.server.nextcloud.system.apps.app_updates).join('<br>')}`;
return {
content, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
content, html: true, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
};
},
storagesTooltip() {
@ -302,7 +271,9 @@ export default {
+ `${this.server.nextcloud.shares.num_shares_room} chat room<br>`
+ `${this.server.nextcloud.shares.num_shares_link} private link<br>`
+ `${this.server.nextcloud.shares.num_shares_link_no_password} public link<br>`
+ '<br><sup>*</sup>Federated shares: sent/received';
+ '<br>Federated shares:<br><br>'
+ `${this.server.nextcloud.shares.num_fed_shares_sent} sent<br>`
+ `${this.server.nextcloud.shares.num_fed_shares_received} received<br>`;
return {
content, html: true, trigger: 'hover focus', delay: 250, classes: 'nc-tooltip',
};
@ -351,6 +322,9 @@ export default {
font-size: 105%;
margin-left: .25rem;
}
small {
opacity: .66;
}
hr {
color: var(--widget-text-color);
border: none;
@ -376,14 +350,13 @@ export default {
margin: 0 0 1rem 0;
}
p.brand {
margin: 0 0 .23rem 0;
margin: 0;
font-size: 135%;
font-weight: 800;
letter-spacing: 3px;
}
p.version {
font-size: 80%;
opacity: .66;
p.version small {
font-size: 75%;
}
p.username {
font-size: 110%;
@ -392,17 +365,16 @@ export default {
}
}
p.login {
font-size: 90%;
small {
opacity: .75;
margin-left: .25rem;
span {
font-size: 90%;
margin-right: .25rem;
}
}
}
div.server-info {
span[data-has-updates] {
color: var(--success);
padding-left: .75rem;
margin-left: 0.5rem;
}
}
}

View File

@ -1,6 +1,6 @@
import { serviceEndpoints } from '@/utils/defaults';
import { convertBytes, formatNumber, getTimeAgo } from '@/utils/MiscHelpers';
// //import { NcdCap } from '@/utils/ncd';
// //import { NcdCap, NcdUsr } from '@/utils/ncd';
/** Reusable mixin for Nextcloud widgets */
export default {
@ -11,6 +11,19 @@ export default {
activity: null,
},
capabilitiesLastUpdated: 0,
user: {
id: null,
isAdmin: false,
displayName: null,
email: null,
quota: {
relative: null,
total: null,
used: null,
free: null,
quota: null,
},
},
};
},
computed: {
@ -24,6 +37,9 @@ export default {
},
password() {
if (!this.options.password) this.error('An app-password is required');
if (!/^([a-z0-9]{5}-){4}[a-z0-9]{5}$/i.test(this.options.password)) {
this.error('Please use an app-password for this widget, not your login password.');
}
return this.options.password;
},
headers() {
@ -33,6 +49,9 @@ export default {
Authorization: `Basic ${window.btoa(`${this.username}:${this.password}`)}`,
};
},
capabilitiesTtl() {
return (parseInt(this.options.capabilitiesTtl, 10) || 3600) * 1000;
},
proxyReqEndpoint() {
const baseUrl = process.env.VUE_APP_DOMAIN || window.location.origin;
return `${baseUrl}${serviceEndpoints.corsProxy}`;
@ -40,21 +59,23 @@ export default {
},
methods: {
endpoint(id) {
const endpoints = {
capabilities: `${this.hostname}/ocs/v1.php/cloud/capabilities`,
user: `${this.hostname}/ocs/v1.php/cloud/users/${this.username}`,
serverinfo: `${this.hostname}/ocs/v2.php/apps/serverinfo/api/v1/info`,
};
return endpoints[id];
switch (id) {
case 'capabilities':
default:
return `${this.hostname}/ocs/v1.php/cloud/capabilities`;
case 'user':
return `${this.hostname}/ocs/v1.php/cloud/users/${this.username}`;
case 'serverinfo':
return `${this.hostname}/ocs/v2.php/apps/serverinfo/api/v1/info`;
}
},
fetchCapabilities() {
const promise = Promise.resolve();
if ((new Date().getTime()) - this.capabilitiesLastUpdated > 3600000) {
promise.then(() => this.makeRequest(this.endpoint('capabilities'), this.headers))
// //promise.then(() => NcdCap)
loadCapabilities() {
if ((new Date().getTime()) - this.capabilitiesLastUpdated > this.capabilitiesTtl) {
return this.makeRequest(this.endpoint('capabilities'), this.headers)
// //return Promise.resolve(NcdCap)
.then(this.processCapabilities);
}
return promise;
return Promise.resolve();
},
processCapabilities(data) {
const ocdata = data?.ocs?.data;
@ -69,6 +90,23 @@ export default {
this.version.edition = ocdata?.version?.edition;
this.capabilitiesLastUpdated = new Date().getTime();
},
loadUser() {
return this.makeRequest(this.endpoint('user'), this.headers).then(this.processUser);
// //return Promise.resolve(NcdUsr).then(this.processUser);
},
processUser(userData) {
const user = userData?.ocs?.data;
if (!user) {
this.error('Invalid response');
return;
}
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;
this.user.isAdmin = user.groups && user.groups.includes('admin');
},
formatNumber(number) {
return formatNumber(number);
},