diff options
author | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2021-05-30 12:29:40 +0200 |
---|---|---|
committer | John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com> | 2021-05-30 12:29:40 +0200 |
commit | fec1798301f0dbe6986c775e4596b07ce27145d9 (patch) | |
tree | 7c4689cc35c7c9a35b363d6ec1d23d279cc82d51 | |
parent | a4a5ca65d06700b2524e9cde67151e2475bba6ca (diff) |
Fix mobile details toggleenh/circles
Signed-off-by: John Molakvoæ (skjnldsv) <skjnldsv@protonmail.com>
-rw-r--r-- | src/components/AppContent/AppDetailsToggle.vue | 70 | ||||
-rw-r--r-- | src/components/AppContent/CircleContent.vue | 15 | ||||
-rw-r--r-- | src/components/EntityPicker/ContactsPicker.vue | 2 | ||||
-rw-r--r-- | src/components/MemberList.vue | 60 | ||||
-rw-r--r-- | src/models/member.d.ts | 2 | ||||
-rw-r--r-- | src/models/member.ts | 9 | ||||
-rw-r--r-- | src/views/Contacts.vue | 33 |
7 files changed, 137 insertions, 54 deletions
diff --git a/src/components/AppContent/AppDetailsToggle.vue b/src/components/AppContent/AppDetailsToggle.vue new file mode 100644 index 00000000..f9c86b60 --- /dev/null +++ b/src/components/AppContent/AppDetailsToggle.vue @@ -0,0 +1,70 @@ +<!-- + - @copyright Copyright (c) 2021 John Molakvoæ <skjnldsv@protonmail.com> + - + - @author John Molakvoæ <skjnldsv@protonmail.com> + - + - @license GNU AGPL version 3 or any later version + - + - This program is free software: you can redistribute it and/or modify + - it under the terms of the GNU Affero General Public License as + - published by the Free Software Foundation, either version 3 of the + - License, or (at your option) any later version. + - + - This program is distributed in the hope that it will be useful, + - but WITHOUT ANY WARRANTY; without even the implied warranty of + - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + - GNU Affero General Public License for more details. + - + - You should have received a copy of the GNU Affero General Public License + - along with this program. If not, see <http://www.gnu.org/licenses/>. + - + --> + +<template> + <a v-tooltip="t('contacts', 'Go back to the list')" class="app-details-toggle icon-confirm" href="#" /> +</template> + +<script> +export default { + name: 'AppDetailsToggle', + + beforeMount() { + this.toggleAppNavigationButton(true) + }, + + beforeDestroy() { + this.toggleAppNavigationButton(false) + }, + + methods: { + toggleAppNavigationButton(hide = true) { + const appNavigationToggle = document.querySelector('.app-navigation .app-navigation-toggle') + if (appNavigationToggle) { + appNavigationToggle.style.display = hide ? 'none' : null + } + }, + }, +} +</script> + +<style lang="scss" scoped> +.app-details-toggle { + position: absolute; + width: 44px; + height: 44px; + padding: 14px; + cursor: pointer; + opacity: .6; + font-size: 16px; + line-height: 17px; + transform: rotate(180deg); + background-color: var(--color-main-background); + z-index: 2000; + + &:active, + &:hover, + &:focus { + opacity: 1; + } +} +</style> diff --git a/src/components/AppContent/CircleContent.vue b/src/components/AppContent/CircleContent.vue index f49f76cf..d5e22f15 100644 --- a/src/components/AppContent/CircleContent.vue +++ b/src/components/AppContent/CircleContent.vue @@ -35,8 +35,10 @@ </div> <div v-else id="app-content-wrapper"> + <AppDetailsToggle v-if="isMobile && showDetails" @click.native.stop.prevent="hideDetails" /> + <!-- member list --> - <MemberList :list="members" :loading="loadingList" /> + <MemberList :list="members" :loading="loadingList" :show-details.sync="showDetails" /> <!-- main contacts details --> <CircleDetails :circle="circle"> @@ -73,9 +75,11 @@ <script> import AppContent from '@nextcloud/vue/dist/Components/AppContent' import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent' +import isMobile from '@nextcloud/vue/dist/Mixins/isMobile' import Login from 'vue-material-design-icons/Login' +import AppDetailsToggle from '../AppContent/AppDetailsToggle' import CircleDetails from '../CircleDetails' import MemberList from '../MemberList' import RouterMixin from '../../mixins/RouterMixin' @@ -87,13 +91,14 @@ export default { components: { AppContent, + AppDetailsToggle, CircleDetails, EmptyContent, Login, MemberList, }, - mixins: [RouterMixin], + mixins: [isMobile, RouterMixin], props: { loading: { @@ -106,6 +111,7 @@ export default { return { loadingJoin: false, loadingList: false, + showDetails: false, } }, @@ -168,6 +174,11 @@ export default { } }, + + // Hide the circle details + hideDetails() { + this.showDetails = false + }, }, } </script> diff --git a/src/components/EntityPicker/ContactsPicker.vue b/src/components/EntityPicker/ContactsPicker.vue index 35b842f1..ef6f0f3f 100644 --- a/src/components/EntityPicker/ContactsPicker.vue +++ b/src/components/EntityPicker/ContactsPicker.vue @@ -9,7 +9,7 @@ <!-- contacts picker --> <EntityPicker v-else-if="showPicker" - :confirm-label="t('contacts', 'Add to {group}', { group: pickerforGroup.name})" + :confirm-label="t('contacts', 'Add to {group}', { group: pickerforGroup.name })" :data-types="pickerTypes" :data-set="pickerData" @close="onContactPickerClose" diff --git a/src/components/MemberList.vue b/src/components/MemberList.vue index 5336f8bc..55652ec3 100644 --- a/src/components/MemberList.vue +++ b/src/components/MemberList.vue @@ -33,11 +33,16 @@ </EmptyContent> </AppContentList> - <AppContentList v-else :class="{ 'icon-loading': loading }"> + <AppContentList v-else :class="{ 'icon-loading': loading, showdetails: showDetails }"> <div class="members-list__new"> <button class="icon-add" @click="onShowPicker(circle.id)"> {{ t('contacts', 'Add members') }} </button> + <button v-if="isMobile" + class="icon-info" + @click="showCircleDetails"> + {{ t('contacts', 'Show circle details') }} + </button> </div> <VirtualList class="members-list" @@ -48,9 +53,9 @@ <!-- member picker --> <EntityPicker v-if="showPicker" - :confirm-label="t('contacts', 'Add to {circle}', { circle: circle.displayName})" + :confirm-label="t('contacts', 'Add to {circle}', { circle: circle.displayName })" :data-types="pickerTypes" - :data-set="pickerData" + :data-set="filteredPickerData" :internal-search="false" :loading="pickerLoading" :selection.sync="pickerSelection" @@ -63,6 +68,7 @@ <script> import AppContentList from '@nextcloud/vue/dist/Components/AppContentList' import EmptyContent from '@nextcloud/vue/dist/Components/EmptyContent' +import isMobile from '@nextcloud/vue/dist/Mixins/isMobile' import VirtualList from 'vue-virtual-scroll-list' import MembersListItem from './MembersList/MembersListItem' @@ -72,7 +78,7 @@ import RouterMixin from '../mixins/RouterMixin' import { getRecommendations, getSuggestions } from '../services/collaborationAutocompletion' import { showError, showWarning } from '@nextcloud/dialogs' import { subscribe } from '@nextcloud/event-bus' -import { SHARES_TYPES_MEMBER_MAP, CIRCLES_MEMBER_GROUPING, MemberTypes } from '../models/constants.ts' +import { SHARES_TYPES_MEMBER_MAP, CIRCLES_MEMBER_GROUPING } from '../models/constants.ts' export default { name: 'MemberList', @@ -83,7 +89,7 @@ export default { EntityPicker, EmptyContent, }, - mixins: [RouterMixin], + mixins: [isMobile, RouterMixin], props: { list: { @@ -95,11 +101,17 @@ export default { type: Boolean, default: false, }, + + showDetails: { + type: Boolean, + default: false, + }, }, data() { return { MembersListItem, + pickerLoading: false, showPicker: false, showPickerIntro: true, @@ -121,20 +133,18 @@ export default { return this.$store.getters.getCircle(this.selectedCircle) }, - filteredList() { + groupedList() { // Group per userType - const groupedList = this.list.reduce(function(r, a) { - // If the user type is a circle, this could originate from multiple sources - const userType = a.userType !== MemberTypes.CIRCLE - ? a.userType - : a.basedOn.source - - r[userType] = r[userType] || [] - r[userType].push(a) - return r + return this.list.reduce(function(list, member) { + const userType = member.userType + list[userType] = list[userType] || [] + list[userType].push(member) + return list }, Object.create(null)) + }, - return Object.keys(groupedList) + filteredList() { + return Object.keys(this.groupedList) // Object.keys returns string .map(type => parseInt(type, 10)) // Map populated types to the group entry @@ -143,7 +153,7 @@ export default { .map(group => [{ heading: true, ...group, - }, ...(groupedList[group.type] || [])]) + }, ...(this.groupedList[group.type] || [])]) // Merging sub-arrays .flat() }, @@ -151,6 +161,18 @@ export default { hasMembers() { return this.filteredList.length > 0 }, + + filteredPickerData() { + return this.pickerData.filter(entity => { + const type = SHARES_TYPES_MEMBER_MAP[entity.shareType] + const list = this.groupedList[type] + if (list) { + return list.find(member => member.userId === entity.shareWith) === undefined + } + // If the type doesn't exists, there is no member of this type + return true + }) + }, }, mounted() { @@ -249,6 +271,10 @@ export default { this.pickerData = [] this.pickerSelection = {} }, + + showCircleDetails() { + this.$emit('update:showDetails', true) + }, }, } </script> diff --git a/src/models/member.d.ts b/src/models/member.d.ts index b779c194..ea3a75e9 100644 --- a/src/models/member.d.ts +++ b/src/models/member.d.ts @@ -59,7 +59,7 @@ export default class Member { /** * Member based on source */ - get basedOn(): Object; + get basedOn(): any; /** * Member level * diff --git a/src/models/member.ts b/src/models/member.ts index b62e6aad..4707a65a 100644 --- a/src/models/member.ts +++ b/src/models/member.ts @@ -21,7 +21,7 @@ */ import Circle from './circle' -import { MemberLevel, MemberLevels, MemberType } from './constants' +import { MemberLevel, MemberLevels, MemberType, MemberTypes } from './constants' export default class Member { @@ -95,13 +95,16 @@ export default class Member { * Member type */ get userType(): MemberType { - return this._data.userType + // If the user type is a circle, this could originate from multiple sources + return this._data.userType !== MemberTypes.CIRCLE + ? this._data.userType + : this.basedOn.source } /** * Member based on source */ - get basedOn(): Object { + get basedOn(): any { return this._data.basedOn } diff --git a/src/views/Contacts.vue b/src/views/Contacts.vue index c336115f..a616377b 100644 --- a/src/views/Contacts.vue +++ b/src/views/Contacts.vue @@ -24,10 +24,7 @@ <template> <Content app-name="contacts"> <!-- go back to list when in details mode --> - <a v-if="selectedContact && isMobile" - class="app-details-toggle icon-confirm" - href="#" - @click.stop.prevent="showList" /> + <AppDetailsToggle v-if="isMobile && selectedContact" @click.native.stop.prevent="showList" /> <!-- new-contact-button + navigation + settings --> <RootNavigation @@ -76,6 +73,7 @@ import Modal from '@nextcloud/vue/dist/Components/Modal' import { showError } from '@nextcloud/dialogs' import { VCardTime } from 'ical.js' +import AppDetailsToggle from '../components/AppContent/AppDetailsToggle' import CircleContent from '../components/AppContent/CircleContent' import ContactsContent from '../components/AppContent/ContactsContent' import ContactsPicker from '../components/EntityPicker/ContactsPicker' @@ -91,6 +89,7 @@ export default { name: 'Contacts', components: { + AppDetailsToggle, AppNavigationNew, CircleContent, ContactsContent, @@ -399,29 +398,3 @@ export default { }, } </script> - -<style lang="scss" scoped> -.app-details-toggle { - position: absolute; - width: 44px; - height: 44px; - padding: 14px; - cursor: pointer; - opacity: .6; - font-size: 16px; - line-height: 17px; - transform: rotate(180deg); - background-color: var(--color-main-background); - z-index: 2000; - &:active, - &:hover, - &am |