Status integration

Signed-off-by: Julius Härtl <jus@bitgrid.net>
This commit is contained in:
Julius Härtl 2020-08-04 11:58:14 +02:00
parent ae6be0c110
commit 3be3c34e39
No known key found for this signature in database
GPG Key ID: 4C614C6ED2CDE6DF
4 changed files with 101 additions and 9 deletions

View File

@ -1,6 +1,12 @@
<template>
<div id="app-dashboard">
<h2>{{ greeting.icon }} {{ greeting.text }}</h2>
<div class="statuses">
<div v-for="status in registeredStatus"
:id="'status-' + status"
:key="status"
:ref="'status-' + status" />
</div>
<Draggable v-model="layout" class="panels" @end="saveLayout">
<div v-for="panelId in layout" :key="panels[panelId].id" class="panel">
@ -73,7 +79,9 @@ export default {
data() {
return {
timer: new Date(),
registeredStatus: [],
callbacks: {},
callbacksStatus: {},
panels,
firstRun,
displayName: getCurrentUser()?.displayName,
@ -81,6 +89,7 @@ export default {
layout: loadState('dashboard', 'layout').filter((panelId) => panels[panelId]),
modal: false,
appStoreUrl: generateUrl('/settings/apps'),
statuses: {},
}
},
computed: {
@ -89,18 +98,18 @@ export default {
const shouldShowName = this.displayName && this.uid !== this.displayName
if (time > 18) {
return { icon: '🌙', text: shouldShowName ? t('dashboard', 'Good evening, {name}', { name: this.name }) : t('dashboard', 'Good evening') }
return { icon: '🌙', text: shouldShowName ? t('dashboard', 'Good evening, {name}', { name: this.displayName }) : t('dashboard', 'Good evening') }
}
if (time > 12) {
return { icon: '☀', text: shouldShowName ? t('dashboard', 'Good afternoon, {name}', { name: this.name }) : t('dashboard', 'Good afternoon') }
return { icon: '☀', text: shouldShowName ? t('dashboard', 'Good afternoon, {name}', { name: this.displayName }) : t('dashboard', 'Good afternoon') }
}
if (time === 12) {
return { icon: '🍽', text: shouldShowName ? t('dashboard', 'Time for lunch, {name}', { name: this.name }) : t('dashboard', 'Time for lunch') }
return { icon: '🍽', text: shouldShowName ? t('dashboard', 'Time for lunch, {name}', { name: this.displayName }) : t('dashboard', 'Time for lunch') }
}
if (time > 5) {
return { icon: '🌄', text: shouldShowName ? t('dashboard', 'Good morning, {name}', { name: this.name }) : t('dashboard', 'Good morning') }
return { icon: '🌄', text: shouldShowName ? t('dashboard', 'Good morning, {name}', { name: this.displayName }) : t('dashboard', 'Good morning') }
}
return { icon: '🦉', text: shouldShowName ? t('dashboard', 'Have a night owl, {name}', { name: this.name }) : t('dashboard', 'Have a night owl') }
return { icon: '🦉', text: shouldShowName ? t('dashboard', 'Have a night owl, {name}', { name: this.displayName }) : t('dashboard', 'Have a night owl') }
},
isActive() {
return (panel) => this.layout.indexOf(panel.id) > -1
@ -120,6 +129,20 @@ export default {
callbacks() {
this.rerenderPanels()
},
callbacksStatus() {
for (const app in this.callbacksStatus) {
const element = this.$refs['status-' + app]
if (this.statuses[app] && this.statuses[app].mounted) {
continue
}
if (element) {
this.callbacksStatus[app](element[0])
Vue.set(this.statuses, app, { mounted: true })
} else {
console.error('Failed to register panel in the frontend as no backend data was provided for ' + app)
}
}
},
},
mounted() {
setInterval(() => {
@ -136,6 +159,12 @@ export default {
register(app, callback) {
Vue.set(this.callbacks, app, callback)
},
registerStatus(app, callback) {
this.registeredStatus.push(app)
this.$nextTick(() => {
Vue.set(this.callbacksStatus, app, callback)
})
},
rerenderPanels() {
for (const app in this.callbacks) {
const element = this.$refs[app]
@ -153,7 +182,6 @@ export default {
}
}
},
saveLayout() {
axios.post(generateUrl('/apps/dashboard/layout'), {
layout: this.layout.join(','),
@ -190,7 +218,7 @@ export default {
text-align: center;
font-size: 32px;
line-height: 130%;
padding: 80px 16px 32px;
padding: 80px 16px 0px;
}
.panels {
@ -305,4 +333,15 @@ export default {
transition: transform 1s;
}
.statuses {
display: flex;
flex-direction: row;
justify-content: center;
margin-bottom: 40px;
& > div {
max-width: 200px;
}
}
</style>

View File

@ -8,4 +8,5 @@ const Instance = new Dashboard({}).$mount('#app')
window.OCA.Dashboard = {
register: (app, callback) => Instance.register(app, callback),
registerStatus: (app, callback) => Instance.registerStatus(app, callback),
}

View File

@ -20,9 +20,10 @@
-->
<template>
<li>
<li :class="{ inline }">
<div id="user-status-menu-item">
<span
v-if="!inline"
id="user-status-menu-item__header"
:title="displayName">
{{ displayName }}
@ -71,6 +72,12 @@ export default {
ActionButton,
SetStatusModal,
},
props: {
inline: {
type: Boolean,
default: false,
},
},
data() {
return {
isModalOpen: false,
@ -237,7 +244,7 @@ export default {
</script>
<style lang="scss">
#user-status-menu-item {
li:not(.inline) #user-status-menu-item {
&__header {
display: block;
color: var(--color-main-text);
@ -270,4 +277,33 @@ export default {
}
}
}
.inline #user-status-menu-item__subheader {
width: 100%;
> button {
background-color: var(--color-main-background);
background-size: 16px;
border: 0;
border-radius: var(--border-radius-pill);
font-weight: normal;
font-size: 0.875em;
padding-left: 40px;
&:hover,
&:focus {
background-color: var(--color-background-hover);
}
&.icon-loading-small {
&::after {
left: 21px;
}
}
}
}
li {
list-style-type: none;
}
</style>

View File

@ -20,4 +20,20 @@ const app = new Vue({
store,
}).$mount('li[data-id="user_status-menuitem"]')
document.addEventListener('DOMContentLoaded', function() {
if (!OCA.Dashboard) {
return
}
OCA.Dashboard.registerStatus('status', (el) => {
const Dashboard = Vue.extend(App)
return new Dashboard({
propsData: {
inline: true,
},
store,
}).$mount(el)
})
})
export { app }