From 3be3c34e39f5066ea0161fa2ca5ede1fa0211f39 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Julius=20H=C3=A4rtl?= <jus@bitgrid.net>
Date: Tue, 4 Aug 2020 11:58:14 +0200
Subject: [PATCH] Status integration
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

Signed-off-by: Julius Härtl <jus@bitgrid.net>
---
 apps/dashboard/src/App.vue                    | 53 ++++++++++++++++---
 apps/dashboard/src/main.js                    |  1 +
 apps/user_status/src/App.vue                  | 40 +++++++++++++-
 apps/user_status/src/main-user-status-menu.js | 16 ++++++
 4 files changed, 101 insertions(+), 9 deletions(-)

diff --git a/apps/dashboard/src/App.vue b/apps/dashboard/src/App.vue
index f0a47ea535d..2104c879dae 100644
--- a/apps/dashboard/src/App.vue
+++ b/apps/dashboard/src/App.vue
@@ -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>
diff --git a/apps/dashboard/src/main.js b/apps/dashboard/src/main.js
index e1c2c59a10f..74d7cb69d4d 100644
--- a/apps/dashboard/src/main.js
+++ b/apps/dashboard/src/main.js
@@ -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),
 }
diff --git a/apps/user_status/src/App.vue b/apps/user_status/src/App.vue
index 116c7a0ca47..c9e95fa87fd 100644
--- a/apps/user_status/src/App.vue
+++ b/apps/user_status/src/App.vue
@@ -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>
diff --git a/apps/user_status/src/main-user-status-menu.js b/apps/user_status/src/main-user-status-menu.js
index 795f41df4e7..c6d23337526 100644
--- a/apps/user_status/src/main-user-status-menu.js
+++ b/apps/user_status/src/main-user-status-menu.js
@@ -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 }
-- 
GitLab