diff options
author | julia.kirschenheuter <julia.kirschenheuter@nextcloud.com> | 2022-10-11 09:58:26 +0300 |
---|---|---|
committer | julia.kirschenheuter <julia.kirschenheuter@nextcloud.com> | 2022-10-14 10:45:29 +0300 |
commit | bd536c0eaf6f359a9a2a51802d66bcbdcc176e52 (patch) | |
tree | f15ce24230bee9aaaa2796deb8b7bce4f675cc99 | |
parent | 31cb3064b31f764ec5ead41483febd3ca2e895ab (diff) |
Create modal window for contacts settings
Signed-off-by: julia.kirschenheuter <julia.kirschenheuter@nextcloud.com>
-rw-r--r-- | src/components/AppNavigation/ContactsSettings.vue | 177 | ||||
-rw-r--r-- | src/components/AppNavigation/RootNavigation.vue | 49 | ||||
-rw-r--r-- | src/components/AppNavigation/Settings/SettingsAddressbook.vue | 10 | ||||
-rw-r--r-- | src/components/AppNavigation/SettingsSection.vue | 125 | ||||
-rw-r--r-- | src/models/constants.d.ts | 1 | ||||
-rw-r--r-- | src/models/constants.ts | 3 |
6 files changed, 224 insertions, 141 deletions
diff --git a/src/components/AppNavigation/ContactsSettings.vue b/src/components/AppNavigation/ContactsSettings.vue new file mode 100644 index 00000000..a355bde3 --- /dev/null +++ b/src/components/AppNavigation/ContactsSettings.vue @@ -0,0 +1,177 @@ +<!-- + - @copyright Copyright (c) 2022 Julia Kirschenheuter <julia.kirschenheuter@nextcloud.com> + - + - @author Julia Kirschenheuter <julia.kirschenheuter@nextcloud.com> + - + - @license AGPL-3.0-or-later + - + - 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> + <AppSettingsDialog id="app-settings-dialog" + :title="t('contacts', 'Contacts settings')" + :show-navigation="true" + :open.sync="showSettings"> + <AppSettingsSection id="general-settings" :title="t('contacts', 'General settings')"> + <CheckboxRadioSwitch :checked="enableSocialSync" + :loading="enableSocialSyncLoading" + :disabled="enableSocialSyncLoading" + class="social-sync__checkbox contacts-settings-modal__form__row" + @update:checked="toggleSocialSync"> + <div class="social-sync__checkbox__label"> + <span> + {{ t('contacts', 'Update avatars from social media') }} + <em>{{ t('contacts', '(refreshed once per week)') }}</em> + </span> + </div> + </CheckboxRadioSwitch> + <SettingsSortContacts class="contacts-settings-modal__form__row" /> + </AppSettingsSection> + <AppSettingsSection id="address-books" :title="t('contacts', 'Address books')"> + <div class="contacts-settings-modal__form"> + <div class="contacts-settings-modal__form__row"> + <ul id="addressbook-list" class="addressbook-list"> + <SettingsAddressbook v-for="addressbook in addressbooks" :key="addressbook.id" :addressbook="addressbook" /> + </ul> + </div> + <SettingsNewAddressbook class="contacts-settings-modal__form__row settings-new-addressbook" :addressbooks="addressbooks" /> + <SettingsImportContacts :addressbooks="addressbooks" + class="contacts-settings-modal__form__row" + @clicked="onClickImport" + @file-loaded="onLoad" /> + </div> + </AppSettingsSection> + </AppSettingsDialog> +</template> + +<script> + +import axios from '@nextcloud/axios' +import { generateUrl } from '@nextcloud/router' +import { loadState } from '@nextcloud/initial-state' +import SettingsAddressbook from './Settings/SettingsAddressbook' +import SettingsNewAddressbook from './Settings/SettingsNewAddressbook' +import SettingsImportContacts from './Settings/SettingsImportContacts' +import SettingsSortContacts from './Settings/SettingsSortContacts' +import CheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch' +import { CONTACTS_SETTINGS } from '../../models/constants.ts' +import { NcAppSettingsDialog as AppSettingsDialog, NcAppSettingsSection as AppSettingsSection } from '@nextcloud/vue' + +export default { + name: 'ContactsSettings', + components: { + AppSettingsDialog, + AppSettingsSection, + SettingsAddressbook, + SettingsNewAddressbook, + SettingsImportContacts, + SettingsSortContacts, + CheckboxRadioSwitch, + }, + props: { + open: { + required: true, + type: Boolean, + }, + }, + data() { + return { + CONTACTS_SETTINGS, + allowSocialSync: loadState('contacts', 'allowSocialSync') !== 'no', + enableSocialSync: loadState('contacts', 'enableSocialSync') !== 'no', + enableSocialSyncLoading: false, + showSettings: false, + } + }, + computed: { + // store getters + addressbooks() { + return this.$store.getters.getAddressbooks + }, + }, + watch: { + showSettings(value) { + if (!value) { + this.$emit('update:open', value) + } + }, + async open(value) { + if (value) { + await this.onOpen() + } + }, + }, + methods: { + onClickImport(event) { + this.$emit('clicked', event) + }, + async toggleSocialSync() { + this.enableSocialSync = !this.enableSocialSync + this.enableSocialSyncLoading = true + + // store value + let setting = 'yes' + this.enableSocialSync ? setting = 'yes' : setting = 'no' + try { + await axios.put(generateUrl('apps/contacts/api/v1/social/config/user/enableSocialSync'), { + allow: setting, + }) + } finally { + this.enableSocialSyncLoading = false + } + }, + onLoad(event) { + this.$emit('file-loaded', false) + }, + async onOpen() { + this.showSettings = true + }, + }, +} +</script> + +<style scoped> +>>> .app-settings__title { + padding: 20px 0; + margin-bottom: 0; +} + +.app-settings-section { + margin-bottom: 45px; +} + +.social-sync__checkbox, .settings-new-addressbook { + margin-bottom: 20px; +} + +.contacts-settings-modal__form__row >>> .material-design-icon { + justify-content: flex-start; +} + +.settings-new-addressbook >>> .new-addressbook-input { + min-height: 44px; + height: 44px; + width: 100%; +} + +.settings-new-addressbook >>> .icon-confirm { + min-height: 44px; + height: 44px; + border-color: var(--color-border-dark) !important; + border-left: none; +} + +</style> diff --git a/src/components/AppNavigation/RootNavigation.vue b/src/components/AppNavigation/RootNavigation.vue index 62e9a1c3..9a91fd00 100644 --- a/src/components/AppNavigation/RootNavigation.vue +++ b/src/components/AppNavigation/RootNavigation.vue @@ -177,33 +177,43 @@ </template> <!-- settings --> + <template #footer> - <AppNavigationSettings v-if="!loading" :title="appNavigationSettingsTitle"> - <SettingsSection /> - </AppNavigationSettings> + <div class="contacts-settings"> + <Button v-if="!loading" + class="contacts-settings-button" + :close-after-click="true" + @click="showContactsSettings"> + <template #icon> + <Cog :size="20" /> + </template> + {{ CONTACTS_SETTINGS }} + </Button> + </div> </template> + <ContactsSettings :open.sync="showSettings" /> </AppNavigation> </template> <script> -import { GROUP_ALL_CONTACTS, CHART_ALL_CONTACTS, GROUP_NO_GROUP_CONTACTS, GROUP_RECENTLY_CONTACTED, ELLIPSIS_COUNT, CIRCLE_DESC } from '../../models/constants.ts' +import { GROUP_ALL_CONTACTS, CHART_ALL_CONTACTS, GROUP_NO_GROUP_CONTACTS, GROUP_RECENTLY_CONTACTED, ELLIPSIS_COUNT, CIRCLE_DESC, CONTACTS_SETTINGS } from '../../models/constants.ts' -import ActionButton from '@nextcloud/vue/dist/Components/NcActionButton' import ActionInput from '@nextcloud/vue/dist/Components/NcActionInput' import ActionText from '@nextcloud/vue/dist/Components/NcActionText' import AppNavigation from '@nextcloud/vue/dist/Components/NcAppNavigation' +import Button from '@nextcloud/vue/dist/Components/NcButton' import NcCounterBubble from '@nextcloud/vue/dist/Components/NcCounterBubble' import AppNavigationItem from '@nextcloud/vue/dist/Components/NcAppNavigationItem' -import AppNavigationSettings from '@nextcloud/vue/dist/Components/NcAppNavigationSettings' import AppNavigationCaption from '@nextcloud/vue/dist/Components/NcAppNavigationCaption' import IconLoading from '@nextcloud/vue/dist/Components/NcLoadingIcon' import naturalCompare from 'string-natural-compare' import CircleNavigationItem from './CircleNavigationItem' +import Cog from 'vue-material-design-icons/Cog.vue' +import ContactsSettings from './ContactsSettings' import GroupNavigationItem from './GroupNavigationItem' import NewCircleIntro from '../EntityPicker/NewCircleIntro' -import SettingsSection from './SettingsSection' import isCirclesEnabled from '../../services/isCirclesEnabled' import isContactsInteractionEnabled from '../../services/isContactsInteractionEnabled' @@ -220,15 +230,16 @@ export default { name: 'RootNavigation', components: { - ActionButton, ActionInput, ActionText, AppNavigation, + Button, NcCounterBubble, AppNavigationItem, - AppNavigationSettings, AppNavigationCaption, CircleNavigationItem, + Cog, + ContactsSettings, GroupNavigationItem, IconContact, IconUser, @@ -237,7 +248,6 @@ export default { IconLoading, IconRecentlyContacted, NewCircleIntro, - SettingsSection, }, mixins: [RouterMixin], @@ -257,6 +267,7 @@ export default { data() { return { CIRCLE_DESC, + CONTACTS_SETTINGS, ELLIPSIS_COUNT, GROUP_ALL_CONTACTS, CHART_ALL_CONTACTS, @@ -277,13 +288,12 @@ export default { collapsedGroups: true, collapsedCircles: true, + + showSettings: false, } }, computed: { - appNavigationSettingsTitle() { - return t('contacts', 'Contacts settings') - }, // store variables circles() { return this.$store.getters.getCircles @@ -444,6 +454,13 @@ export default { closeNewCircleIntro() { this.isNewCircleModalOpen = false }, + + /** + * Shows the contacts settings + */ + showContactsSettings() { + this.showSettings = true + }, }, } </script> @@ -471,4 +488,10 @@ $caption-padding: 22px; opacity: .7; font-weight: bold; } +.contacts-settings { + padding: calc(var(--default-grid-baseline, 4px)*2); +} +.contacts-settings-button { + width: 100%; +} </style> diff --git a/src/components/AppNavigation/Settings/SettingsAddressbook.vue b/src/components/AppNavigation/Settings/SettingsAddressbook.vue index 29f6c378..b3d50408 100644 --- a/src/components/AppNavigation/Settings/SettingsAddressbook.vue +++ b/src/components/AppNavigation/Settings/SettingsAddressbook.vue @@ -305,6 +305,7 @@ export default { align-items: center; white-space: nowrap; text-overflow: ellipsis; + padding: 5px 0; > .addressbook__name { + a, @@ -344,9 +345,9 @@ export default { } .settings-addressbook-list { display: flex; - gap: 4px; - li { - width: calc(100% - 44px); + width: 100%; + .material-design-icon { + justify-content: flex-start; } } .addressbook__share { @@ -354,4 +355,7 @@ export default { border: none; box-shadow: none; } +.addressbook-shares { + padding-top: 10px; +} </style> diff --git a/src/components/AppNavigation/SettingsSection.vue b/src/components/AppNavigation/SettingsSection.vue deleted file mode 100644 index 2a33fd4a..00000000 --- a/src/components/AppNavigation/SettingsSection.vue +++ /dev/null @@ -1,125 +0,0 @@ -<!-- - - @copyright Copyright (c) 2018 John Molakvoæ <skjnldsv@protonmail.com> - - - - @author John Molakvoæ <skjnldsv@protonmail.com> - - @author Matthias Heinisch <nextcloud@matthiasheinisch.de> - - - - @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> - <div> - <SettingsSortContacts class="settings-section" /> - <CheckboxRadioSwitch :checked="enableSocialSync" - :loading="enableSocialSyncLoading" - :disabled="enableSocialSyncLoading" - class="social-sync__checkbox" - @update:checked="toggleSocialSync"> - <div class="social-sync__checkbox__label"> - <span> - {{ t('contacts', 'Update avatars from social media') }} - <em>{{ t('contacts', '(refreshed once per week)') }}</em> - </span> - </div> - </CheckboxRadioSwitch> - <div class="settings-addressbook-list__header"> - <span>{{ t('contacts', 'Address books') }}</span> - </div> - <ul id="addressbook-list"> - <SettingsAddressbook v-for="addressbook in addressbooks" :key="addressbook.id" :addressbook="addressbook" /> - </ul> - <SettingsNewAddressbook :addressbooks="addressbooks" /> - <SettingsImportContacts :addressbooks="addressbooks" - class="settings-section" - @clicked="onClickImport" - @file-loaded="onLoad" /> - </div> -</template> - -<script> -import axios from '@nextcloud/axios' -import { generateUrl } from '@nextcloud/router' -import { loadState } from '@nextcloud/initial-state' -import SettingsAddressbook from './Settings/SettingsAddressbook' -import SettingsNewAddressbook from './Settings/SettingsNewAddressbook' -import SettingsImportContacts from './Settings/SettingsImportContacts' -import SettingsSortContacts from './Settings/SettingsSortContacts' -import CheckboxRadioSwitch from '@nextcloud/vue/dist/Components/NcCheckboxRadioSwitch' - -export default { - name: 'SettingsSection', - components: { - SettingsAddressbook, - SettingsNewAddressbook, - SettingsImportContacts, - SettingsSortContacts, - CheckboxRadioSwitch, - }, - data() { - return { - allowSocialSync: loadState('contacts', 'allowSocialSync') !== 'no', - enableSocialSync: loadState('contacts', 'enableSocialSync') !== 'no', - enableSocialSyncLoading: false, - } - }, - computed: { - // store getters - addressbooks() { - return this.$store.getters.getAddressbooks - }, - }, - methods: { - onClickImport(event) { - this.$emit('clicked', event) - }, - async toggleSocialSync() { - this.enableSocialSync = !this.enableSocialSync - this.enableSocialSyncLoading = true - - // store value - let setting = 'yes' - this.enableSocialSync ? setting = 'yes' : setting = 'no' - try { - await axios.put(generateUrl('apps/contacts/api/v1/social/config/user/enableSocialSync'), { - allow: setting, - }) - } finally { - this.enableSocialSyncLoading = false - } - }, - onLoad(event) { - this.$emit('file-loaded', false) - }, - }, -} -</script> - -<style lang="scss" scoped> -.social-sync__checkbox { - margin-top: 5px; - - ::v-deep .checkbox-radio-switch__label { - height: unset !important; - } - - ::v-deep .checkbox-radio-switch__icon { - width: 44px; - flex-shrink: 0; - flex-grow: 0; - } -} -</style> diff --git a/src/models/constants.d.ts b/src/models/constants.d.ts index 7364d213..0151fa6d 100644 --- a/src/models/constants.d.ts +++ b/src/models/constants.d.ts @@ -32,6 +32,7 @@ export declare const GROUP_RECENTLY_CONTACTED: DefaultGroup; export declare const CHART_ALL_CONTACTS: DefaultChart; export declare const ROUTE_CIRCLE = "circle"; export declare const ROUTE_CHART = "chart"; +export declare const CONTACTS_SETTINGS: DefaultGroup; export declare const ELLIPSIS_COUNT = 5; export declare const CIRCLE_DESC: string; export declare const CIRCLES_MEMBER_TYPES: { diff --git a/src/models/constants.ts b/src/models/constants.ts index dde4f8df..5624a353 100644 --- a/src/models/constants.ts +++ b/src/models/constants.ts @@ -45,6 +45,9 @@ export const CHART_ALL_CONTACTS: DefaultChart = t('contacts', 'Organization char export const ROUTE_CIRCLE = 'circle' export const ROUTE_CHART = 'chart' +//Contact settings +export const CONTACTS_SETTINGS: DefaultGroup = t('contacts', 'Contacts settings') + // Default max number of items to show in the navigation export const ELLIPSIS_COUNT = 5 |