Skip to content

Commit 8ca4a7a

Browse files
ShGKmeAntreesy
authored andcommitted
refactor(user_status): migrate to Vue 3
Signed-off-by: Grigorii K. Shartsev <[email protected]>
1 parent b10d5d3 commit 8ca4a7a

File tree

13 files changed

+104
-79
lines changed

13 files changed

+104
-79
lines changed

apps/user_status/css/user-status-menu.css

Lines changed: 0 additions & 4 deletions
This file was deleted.

apps/user_status/css/user-status-menu.css.map

Lines changed: 0 additions & 1 deletion
This file was deleted.

apps/user_status/css/user-status-menu.css.map.license

Lines changed: 0 additions & 2 deletions
This file was deleted.

apps/user_status/lib/Listener/BeforeTemplateRenderedListener.php

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,6 @@ public function handle(Event $event): void {
7070
});
7171

7272
Util::addScript('user_status', 'menu');
73-
Util::addStyle('user_status', 'user-status-menu');
73+
Util::addStyle('user_status', 'menu');
7474
}
7575
}

apps/user_status/src/UserStatus.vue

Lines changed: 38 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -4,46 +4,44 @@
44
-->
55

66
<template>
7-
<Fragment>
8-
<NcListItem
9-
v-if="!inline"
10-
class="user-status-menu-item"
11-
compact
12-
:name="visibleMessage"
13-
@click.stop="openModal">
7+
<NcListItem
8+
v-if="!inline"
9+
:class="$style.userStatusMenuItem"
10+
compact
11+
:name="visibleMessage"
12+
@click.stop="openModal">
13+
<template #icon>
14+
<NcUserStatusIcon
15+
:class="$style.userStatusIcon"
16+
:status="statusType"
17+
aria-hidden="true" />
18+
</template>
19+
</NcListItem>
20+
21+
<div v-else>
22+
<!-- Dashboard Status -->
23+
<NcButton @click.stop="openModal">
1424
<template #icon>
1525
<NcUserStatusIcon
16-
class="user-status-icon"
26+
:class="$style.userStatusIcon"
1727
:status="statusType"
1828
aria-hidden="true" />
1929
</template>
20-
</NcListItem>
21-
22-
<div v-else>
23-
<!-- Dashboard Status -->
24-
<NcButton @click.stop="openModal">
25-
<template #icon>
26-
<NcUserStatusIcon
27-
class="user-status-icon"
28-
:status="statusType"
29-
aria-hidden="true" />
30-
</template>
31-
{{ visibleMessage }}
32-
</NcButton>
33-
</div>
34-
<!-- Status management modal -->
35-
<SetStatusModal
36-
v-if="isModalOpen"
37-
:inline="inline"
38-
@close="closeModal" />
39-
</Fragment>
30+
{{ visibleMessage }}
31+
</NcButton>
32+
</div>
33+
<!-- Status management modal -->
34+
<SetStatusModal
35+
v-if="isModalOpen"
36+
:inline="inline"
37+
@close="closeModal" />
4038
</template>
4139

4240
<script>
4341
import { getCurrentUser } from '@nextcloud/auth'
4442
import { subscribe, unsubscribe } from '@nextcloud/event-bus'
4543
import debounce from 'debounce'
46-
import { Fragment } from 'vue-frag'
44+
import { defineAsyncComponent } from 'vue'
4745
import NcButton from '@nextcloud/vue/components/NcButton'
4846
import NcListItem from '@nextcloud/vue/components/NcListItem'
4947
import NcUserStatusIcon from '@nextcloud/vue/components/NcUserStatusIcon'
@@ -55,11 +53,10 @@ export default {
5553
name: 'UserStatus',
5654
5755
components: {
58-
Fragment,
5956
NcButton,
6057
NcListItem,
6158
NcUserStatusIcon,
62-
SetStatusModal: () => import(/* webpackChunkName: 'user-status-modal' */'./components/SetStatusModal.vue'),
59+
SetStatusModal: defineAsyncComponent(() => import('./components/SetStatusModal.vue')),
6360
},
6461
6562
mixins: [OnlineStatusMixin],
@@ -126,7 +123,7 @@ export default {
126123
/**
127124
* Some housekeeping before destroying the component
128125
*/
129-
beforeDestroy() {
126+
beforeUnmount() {
130127
window.removeEventListener('mouseMove', this.mouseMoveListener)
131128
clearInterval(this.heartbeatInterval)
132129
unsubscribe('user_status:status.updated', this.handleUserStatusUpdated)
@@ -179,8 +176,15 @@ export default {
179176
}
180177
</script>
181178
182-
<style lang="scss" scoped>
183-
.user-status-icon {
179+
<style lang="scss" module>
180+
// Note: As for v9.3.0 NcListItem does not support <style scoped>
181+
.userStatusMenuItem,
182+
.userStatusMenuItem * {
183+
// TODO: Vue 3 migration - add box-sizing to core menu component
184+
box-sizing: border-box;
185+
}
186+
187+
.userStatusIcon {
184188
width: 20px;
185189
height: 20px;
186190
margin: calc((var(--default-clickable-area) - 20px) / 2); // 20px icon size

apps/user_status/src/components/ClearAtSelect.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ export default {
3939
},
4040
},
4141
42-
emits: ['select-clear-at'],
42+
emits: ['selectClearAt'],
4343
4444
data() {
4545
return {
@@ -74,7 +74,7 @@ export default {
7474
return
7575
}
7676
77-
this.$emit('select-clear-at', option.clearAt)
77+
this.$emit('selectClearAt', option.clearAt)
7878
},
7979
},
8080
}

apps/user_status/src/components/CustomMessageInput.vue

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ export default {
6161
6262
emits: [
6363
'change',
64-
'select-icon',
64+
'selectIcon',
6565
],
6666
6767
computed: {
@@ -85,14 +85,14 @@ export default {
8585
/**
8686
* Notifies the parent component about a changed input
8787
*
88-
* @param {Event} event The Change Event
88+
* @param {string} value The new input value
8989
*/
90-
onChange(event) {
91-
this.$emit('change', event.target.value)
90+
onChange(value) {
91+
this.$emit('change', value)
9292
},
9393
9494
setIcon(icon) {
95-
this.$emit('select-icon', icon)
95+
this.$emit('selectIcon', icon)
9696
},
9797
},
9898
}

apps/user_status/src/components/OnlineStatusSelect.vue

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -12,10 +12,12 @@
1212
name="user-status-online"
1313
@change="onChange">
1414
<label :for="id" class="user-status-online-select__label">
15-
<NcUserStatusIcon
16-
:status="type"
17-
class="user-status-online-select__icon"
18-
aria-hidden="true" />
15+
<span class="user-status-online-select__icon-wrapper">
16+
<NcUserStatusIcon
17+
:status="type"
18+
class="user-status-online-select__icon"
19+
aria-hidden="true" />
20+
</span>
1921
{{ label }}
2022
<em class="user-status-online-select__subline">{{ subline }}</em>
2123
</label>
@@ -92,10 +94,17 @@ export default {
9294
}
9395
}
9496
97+
&__icon-wrapper {
98+
height: var(--default-clickable-area);
99+
width: var(--default-clickable-area);
100+
display: flex;
101+
align-items: center;
102+
justify-content: center;
103+
}
104+
95105
&__icon {
96106
height: 20px;
97107
width: 20px;
98-
padding: calc((var(--default-clickable-area) - 20px) / 2);
99108
}
100109
101110
&__input:checked + &__label {

apps/user_status/src/components/PredefinedStatusesList.vue

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ export default {
3636
PredefinedStatus,
3737
},
3838
39-
emits: ['select-status'],
39+
emits: ['selectStatus'],
4040
4141
data() {
4242
return {
@@ -80,7 +80,7 @@ export default {
8080
*/
8181
selectStatus(status) {
8282
this.lastSelected = status.id
83-
this.$emit('select-status', status)
83+
this.$emit('selectStatus', status)
8484
},
8585
},
8686
}

apps/user_status/src/menu.js

Lines changed: 18 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,12 @@
33
* SPDX-License-Identifier: AGPL-3.0-or-later
44
*/
55

6-
import { getCSPNonce } from '@nextcloud/auth'
76
import { subscribe } from '@nextcloud/event-bus'
8-
import Vue from 'vue'
7+
import { createApp } from 'vue'
98
import UserStatus from './UserStatus.vue'
109
import store from './store/index.js'
1110

12-
__webpack_nonce__ = getCSPNonce()
11+
import './user-status-icons.css'
1312

1413
const mountPoint = document.getElementById('user_status-menu-entry')
1514

@@ -18,12 +17,17 @@ const mountPoint = document.getElementById('user_status-menu-entry')
1817
*/
1918
function mountMenuEntry() {
2019
const mountPoint = document.getElementById('user_status-menu-entry')
21-
22-
new Vue({
23-
el: mountPoint,
24-
render: (h) => h(UserStatus),
25-
store,
26-
})
20+
// TODO: fix me after Core migration to Vue 3
21+
// In Vue 2 menu items were mounted in place to the menu items
22+
// In Vue 3 they are mounted inside the menu item
23+
// A workaround - replace the menu item with "display: contents" div
24+
const transparentMountPoint = document.createElement('div')
25+
transparentMountPoint.style.display = 'contents'
26+
mountPoint.replaceWith(transparentMountPoint)
27+
28+
createApp(UserStatus)
29+
.use(store)
30+
.mount(transparentMountPoint)
2731
}
2832

2933
if (mountPoint) {
@@ -39,12 +43,10 @@ document.addEventListener('DOMContentLoaded', function() {
3943
}
4044

4145
OCA.Dashboard.registerStatus('status', (el) => {
42-
const Dashboard = Vue.extend(UserStatus)
43-
return new Dashboard({
44-
propsData: {
45-
inline: true,
46-
},
47-
store,
48-
}).$mount(el)
46+
createApp(UserStatus, {
47+
inline: true,
48+
})
49+
.use(store)
50+
.mount(el)
4951
})
5052
})

0 commit comments

Comments
 (0)